date range checking in C# - c#

How to find if a date in the input is within a specific daterange (let's say for example wihtin last 7 days, meaning I will say -7). If it is within last 7 days, do something, else do something else.
I currently could do upto this, but I don't know how to change this further to meet what I want.
string a = "-1"; // These are values that are configurable based on which date is checked. Yesterday means, -1 for example.
string b = "-15"; // -15 means within last 15 days.
DateTime d = input;
DateTime e = d.AddDays(int.Parse(a));
if (d is between datetime.now and e)
{
//do something
}
else do something

First of all, use meaningful names instead of a and b, secondly: use proper data types (you don't use b at all):
int dayOffset = -1;
int lowerBound = -15;
var currentDate = DateTime.Now;
if(input >= currentDate.AddDays(dayOffset) && input <= currentDate)
{ // do smoething }
Using your names:
var currentDate = DateTime.Now;
if(input >= currentDate.AddDays(a) && input <= currentDate)
{ // do smoething }

You can use less than(<) and greater than(>) operator basicly.
I mean you should change your if conditionlike:
if (d >= e && d <= DateTime.Now)

You can try something like this to compare Date portion without Time
string a = "-1"; // These are values that are configurable based on which date is checked. Yesterday means, -1 for example.
string b = "-15"; // -15 means within last 15 days.
DateTime d = new DateTime();
DateTime e = d.AddDays(int.Parse(a));
if (DateTime.Now.Date >= d.Date && e.Date <= d.Date)
{
}

Related

Calculating no of weekends in between the two given date and time fields by considering the time difference and output the difference in minutes

I have two fields startdate and enddate. I need to calculate how many weekends in between two date and time fields and show the result in minutes.
For example start date is 01/11/2019 00:00:00 and end date as 03/11/2019 11:00:00. Below code is returning the difference in minutes correctly as 2100 minutes but when I keep the dates as02/11/2019 08:00 and 03/11/2019 00:00 I am getting the result as 1440 but my expected result is 960 minutes.
I understand that's because I am adding 1440 in code so how to correct this?
public double CountOfWeekEnds(DateTime startDate, DateTime endDate)
{
double weekEndCount = 0;
if (startDate > endDate)
{
DateTime temp = startDate;
startDate = endDate;
endDate = temp;
}
TimeSpan diff = endDate - startDate;
int days = diff.Days;
for (var i = 0; i <= days; i++)
{
var testDate = startDate.AddDays(i);
if (testDate.DayOfWeek == DayOfWeek.Saturday || testDate.DayOfWeek == DayOfWeek.Sunday)
{
if (testDate.Date < endDate.Date)
{
weekEndCount += 1440; // 24h * 60 min
}
else
{
var todayStart = new DateTime(testDate.Year, testDate.Month, testDate.Day, 0, 0, 0);
var difference = (endDate - todayStart).TotalMinutes;
weekEndCount += difference;
}
}
}
return weekEndCount;
}
OK, i simplified what i said a little down to:
DateTime start = new DateTime(2019,11,1,0,0,0);
DateTime end = new DateTime(2019, 11, 3, 11, 0, 0);
TimeSpan diff = end - start;
Console.WriteLine(diff.TotalDays);
int total = 0;
for (int i = 0; i<Math.Ceiling(diff.TotalDays); i++)
{
DateTime test = start.AddDays(i);
Console.WriteLine(test.DayOfWeek);
if (test.DayOfWeek == DayOfWeek.Saturday || test.DayOfWeek == DayOfWeek.Sunday)
{
if (test.Date==start.Date)
{
Console.WriteLine("start");
total += (23 - start.Hour) * 60 + (60 - start.Minute);
}
else if (test.Date==end.Date)
{
Console.WriteLine("end");
total += end.Hour * 60 + end.Minute;
}
else
{
total += 24 * 60;
}
}
Console.WriteLine(test + " total " + total);
}
Console.WriteLine("done");
Console.WriteLine(total);
which counts all saturdays and sundays and allows for start and ends to be partials
(and can someone send a keyboard with actual keys this membrain lark is hampering typings)
Trying to remain as much of the original code as possible, only three minor changes have to be made:
1. Use the actual dates to calculate diff:
TimeSpan diff = endDate.Date - startDate.Date; instead of TimeSpan diff = endDate - startDate;
This is because later in the upcoming for-loop you are trying to evaluate each date in order to say if is a saturday or sunday. Otherwise, you are evaluating if the date 24 (, 48, …) hours after your starting time stamp is a saturday or sunday.
2. Use testDate instead of todayStart in order to calculate difference
difference = (endDate - testDate).TotalMinutes;
instead of
var todayStart = new DateTime(testDate.Year, testDate.Month, testDate.Day, 0, 0, 0);
var difference = (endDate - todayStart).TotalMinutes;
This is because testDate does contain the hours and minutes to calculate the difference in minutes. Otherwise you are just ignoring the day time of the starting day. Note that this correction can lead to a negative difference value if the startDate day time is later than the endDate day time.
3. do not add a whole day if there is only one day to examine in total
That means that if startDate.Date == endDate.Date, you should just calculate the difference between the dates.
if (testDate.Date < endDate.Date && startDate.Date != endDate.Date)
This has to be done because of the code logic: a full day is added for every new day other than the final day and for the final day ~24hours are added or substracted to the final value depending on the day times of the startDate and endDate.
The complete corrected code:
public static double CountOfWeekEnds(DateTime startDate, DateTime endDate)
{
double weekEndCount = 0;
if (startDate > endDate)
{
DateTime temp = startDate;
startDate = endDate;
endDate = temp;
}
TimeSpan diff = endDate.Date - startDate.Date; //instead of endDate - startDate
int days = diff.Days;
for (var i = 0; i <= days; i++)
{
var testDate = startDate.AddDays(i);
//Console.WriteLine(testDate);
if (testDate.DayOfWeek == DayOfWeek.Saturday || testDate.DayOfWeek == DayOfWeek.Sunday) //only weekends count
{
if (testDate.Date < endDate.Date && startDate.Date != endDate.Date) { // added startDate.Date != endDate.Date
weekEndCount += 1440; // 24h * 60 min
//Console.WriteLine("************************add 1440 ");
}
else
{
double difference;
difference = (endDate - testDate).TotalMinutes; //instead of endDate - todayStart
//Console.WriteLine("************************add " + difference);
weekEndCount += difference;
}
}
}
//return days;
return weekEndCount;
}
You need to have a look at this condition:
if (testDate.Date < endDate.Date)
It means that "as long as the ticks of testDate is less than the ticks of endDate".
This condition will be true for all conditions that makes your variable "days" positive.
I think you need to extend this, condition e.g.
if ((endDate - todayStart).TotalMinutes > 1440 )
This way it will check whether it is AT LEAST 24 hours earlier. If it isn't it should go forth with your "else" condition and take the used fraction of the start day into consideration.
Here is a (somewhat) simple solution. Please note that the code could (and probably should) be refactored if it was to be production code. But I tried to optimize it for understandability, since it was your first post...
public static int CalculateWeekendMinutes(DateTime start, DateTime end)
{
int weekendMinutes = 0;
// First and last day will be handled seperately in the end
var firstFullDay = start.AddDays(1).Date;
var lastFullDay = end.AddDays(-1).Date;
TimeSpan limitedSpan = lastFullDay - firstFullDay;
int spanLengthDays = (int)limitedSpan.TotalDays;
var dateIterator = firstFullDay;
// Looping over the limited span allows us to analyse all the full days
while (dateIterator <= lastFullDay)
{
if (dateIterator.DayOfWeek == DayOfWeek.Saturday || dateIterator.DayOfWeek == DayOfWeek.Sunday)
{
weekendMinutes += (24 * 60);
}
dateIterator = dateIterator.AddDays(1);
}
// Finally we can calculate the partial days and add that to our total
weekendMinutes += CalculateMinutesOnFirstDay(start);
weekendMinutes += CalculateMinutesOnLastDay(end);
return weekendMinutes;
}
// Helps us calculate the minutes of the first day in the span
private static int CalculateMinutesOnFirstDay(DateTime date)
{
if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)
{
// We want to know how many minutes there are UNTIL the next midnight
int minutes = (int)(date.Date.AddDays(1) - date).TotalMinutes;
return minutes;
}
else
{
return 0;
}
}
// Helps us calculate the minutes of the last day in the span
private static int CalculateMinutesOnLastDay(DateTime date)
{
if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)
{
// We want to know how many minutes there are SINCE the last midnight
int minutes = (int)(date - date.Date).TotalMinutes;
return minutes;
}
else
{
return 0;
}
}

Date algorithm - Add days without considering leap years

The system I'm working on is built and configured in such a way, where users cannot choose leap years when setting up a recurring payment. This results in all the date-math behind the scenes having to ignore leap years. (I didn't choose this, but this is how it was written)
I have to write a method that takes in a DateTime value, and adds days to the date, ignoring leap years, which essentially means ignoring Feb 29th and pretending it doesn't exist.
For example, If I'm adding 365 days to 1/1/2016, that should result in 1/1/2017, not 12/31/2016.
I'm using .NET, so I can make use of DateTime.IsLeapYear, and other helper methods.
This is a work in progress, and here is what I have so far. I started taking a simpler route, and I'm now realizing that it's going to require a more complex algorithm.
public static DateTime AddDaysToDateWithLeapYearConsideration(DateTime date, int daysToAdd)
{
// Nothing to do
if (daysToAdd == 0)
{
return date;
}
// NOTE: This is an invalid approach; using DateTime.AddDays will take leap years into account
DateTime dateWithAddedDays = date.AddDays(daysToAdd);
const int FEB_28_DAY_OF_YEAR = 59;
int daysToSubtractForLeapYearConsideration = 0;
// The year is a leap year, which is under the feb 28 day threshold, and we're adding enough days to push it over the feb 28 day threshold
// This will result in .NET taking into account the feb 29th (the leap year day), but we have to subtract that leap year day since the system doesn't take feb 29th into account
if (DateTime.IsLeapYear(date.Year) && date.DayOfYear < FEB_28_DAY_OF_YEAR && (date.DayOfYear + daysToAdd > FEB_28_DAY_OF_YEAR))
{
daysToSubtractForLeapYearConsideration++;
}
// The resulting date (after the days are added or subtracted) is a leap year, whose day is past the feburary 28 day threshold, and it's not the same year as the date (i.e. it spans across "n" years)
if (DateTime.IsLeapYear(dateWithAddedDays.Year) && dateWithAddedDays.DayOfYear > FEB_28_DAY_OF_YEAR && dateWithAddedDays.Year != date.Year)
{
daysToSubtractForLeapYearConsideration++;
}
// We determined if the original date should be leap year considered, as well as the resulting date/year with the days added. Now see if there are any years in between
// that we should consider
bool isThereAYearRangeThatWeNeedToEvaluateLeapYearsFor = Math.Abs(date.Year - dateWithAddedDays.Year) > 0;
if (isThereAYearRangeThatWeNeedToEvaluateLeapYearsFor)
{
for (int leapYearEvalIndex = Math.Min(date.Year, dateWithAddedDays.Year); leapYearEvalIndex <= Math.Max(date.Year, dateWithAddedDays.Year); leapYearEvalIndex++)
{
bool isYearPartOfTheYearsThatWeveAlreadyChecked = leapYearEvalIndex == date.Year || leapYearEvalIndex == dateWithAddedDays.Year;
if (!isYearPartOfTheYearsThatWeveAlreadyChecked && DateTime.IsLeapYear(leapYearEvalIndex))
{
daysToSubtractForLeapYearConsideration++;
}
}
}
DateTime dateResult = date.AddDays(daysToAdd - daysToSubtractForLeapYearConsideration);
// The system does not allow 2/29 days, hence all this crazy date math
if (dateResult.Month == 2 && dateResult.Day == 29)
{
dateResult = dateResult.AddDays(1);
}
return dateResult;
}
The logic has to take into account negative numbers as well (i.e. subtracting), which the above code fails on.
The above code by no means works, but I wanted to demonstrate that I'm trying to tackle the problem, and not simply asking without having tried anything.
Edit
I've come up with an algorithm pretty close to David's approach. (I wrote it, and then came back to StackOverflow to check responses).
public static DateTime AddDaysToDateWithLeapYearConsideration(DateTime date, int daysToAdd)
{
// Nothing to do
if (daysToAdd == 0)
{
return date;
}
DateTime dateResult = date;
// Are we adding or subtracting
bool areWeAddingDays = daysToAdd > 0;
int daysToAccountForInRegardToLeapYearDates = 0,
absDaysToAdd = Math.Abs(daysToAdd);
for (int i = 1; i <= absDaysToAdd; i++)
{
dateResult = dateResult.AddDays(areWeAddingDays ? 1 : -1);
if (dateResult.Month == 2 && dateResult.Day == 29)
{
daysToAccountForInRegardToLeapYearDates++;
}
}
dateResult = dateResult.AddDays(areWeAddingDays ? daysToAccountForInRegardToLeapYearDates : -daysToAccountForInRegardToLeapYearDates);
return dateResult;
}
Here is an extension method that works. Will also work if you're adding or subtracting enough days to span multiple leap years.
public static DateTime AddDaysWithoutLeapYear(this DateTime input, int days)
{
var output = input;
if (days != 0)
{
var increment = days > 0 ? 1 : -1; //this will be used to increment or decrement the date.
var daysAbs = Math.Abs(days); //get the absolute value of days to add
var daysAdded = 0; // save the number of days added here
while (daysAdded < daysAbs)
{
output = output.AddDays(increment);
if (!(output.Month == 2 && output.Day == 29)) //don't increment the days added if it is a leap year day
{
daysAdded++;
}
}
}
return output;
}
Might need some more testing, but without using the DateTime Add... functions or too much looping, a possible custom implementation:
public static DateTime AddDaysToDateWithLeapYearConsideration(DateTime date, int daysToAdd)
{
int year = date.Year + daysToAdd / 365, month = date.Month - 1, dir = Math.Sign(daysToAdd);
daysToAdd = (daysToAdd % 365) + date.Day;
int[] months = {31,28,31,30,31,30,31,31,30,31,30,31};
while(daysToAdd > months[month] || daysToAdd < 0){
if(dir ==1) daysToAdd -= months[month];
month += dir;
if(month == 12 || month == -1){
year += dir;
month = dir == -1 ? 11 : 0;
}
if(dir ==-1) daysToAdd += months[month]; //for reverse direction, add previous month
}
return new DateTime(year, ++month,daysToAdd);
}

Calculate End Date when specific duration of days given [duplicate]

This question already has answers here:
Calculate the number of business days between two dates?
(39 answers)
Closed 7 years ago.
I am developing c#.net solution where i have to calculate End Date from start date in date time picker based on provided duration date.(excluding weekends)
i.e.
Start Date: 02/09/2015 days: 5
Start Date = 02/09/2015 + 5 days (Excludes weekends)
End Date = 08/09/2015
thanks you,
Try this,
var startDate = DateTime.Now; // Put your actual start date here
for (int i = 0; i < 5;) // Put number of days to add instead of 5
{
startDate = startDate.AddDays(1);
if (startDate.DayOfWeek == DayOfWeek.Saturday || startDate.DayOfWeek == DayOfWeek.Sunday)
{
continue;
}
i++;
}
var finalDate = startDate;
Assuming your start date is a weekday, just add 7 days to it. The calculation for an arbitrary number of days would be as follows:
DateTime StartDate = new DateTime(2015, 9, 2);
DateTime EndDate = StartDate.AddDays(duration/5*7+duration%5);
Assuming we have an array of businessHolidays, we could account for those as well:
for( var index = 0; index < businessHolidays.length; index++) {
var holiday = businessHolidays[index];
if (holiday.Date >= StartDate.Date && holiday.Date <= EndDate.Date) {
EndDate.AddDays(1);
}
}
Finally, we check the resulting date to see if it falls on a weekend. This is necessary if the start date was a weekend or we pushed the date due to a holiday.
if ( EndDate.DayOfWeek == DayOfWeek.Saturday ) {
EndDate.AddDays(2);
} else if ( EndDate.DayOfWeek == DayOfWeek.Sunday ) {
EndDate.AddDays(1);
}

Regular expression to validate valid time

I need a regular expression to validate time.
Valid values would be from 0:00 to 23:59.
When the time is less than 10:00 it should also support one character numbers.
These are valid values:
9:00
09:00
Try this regular expression:
^(?:[01]?[0-9]|2[0-3]):[0-5][0-9]$
Or to be more distinct:
^(?:0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$
I don't want to steal anyone's hard work but this is exactly what you're looking for, apparently.
using System.Text.RegularExpressions;
public bool IsValidTime(string thetime)
{
Regex checktime =
new Regex(#"^(20|21|22|23|[01]d|d)(([:][0-5]d){1,2})$");
return checktime.IsMatch(thetime);
}
I'd just use DateTime.TryParse().
DateTime time;
string timeStr = "23:00"
if(DateTime.TryParse(timeStr, out time))
{
/* use time or timeStr for your bidding */
}
The regex ^(2[0-3]|[01]d)([:][0-5]d)$ should match 00:00 to 23:59. Don't know C# and hence can't give you the relevant code.
/RS
If you want to allow military and standard with the use of AM and PM (optional and insensitive), then you may want to give this a try.
^(?:(?:0?[1-9]|1[0-2]):[0-5][0-9]\s?(?:[AP][Mm]?|[ap][m]?)?|(?:00?|1[3-9]|2[0-3]):[0-5][0-9])$
Very late to the party but I created this Regex which I found work the best for 24H format (HH:mm:ss OR HH:mm OR H:mm:ss OR H:mm):
private bool TimePatternValidation(string time)
=> new Regex(#"^(([0-1]?[0-9])|([2][0-3]))(:([0-5][0-9])){1,2}$").IsMatch(time);
[RegularExpression(#"^(0[1-9]|1[0-2]):[0-5][0-9]:[0-5][0-9] (am|pm|AM|PM)$",
ErrorMessage = "Invalid Time.")]
Try this
Better!!!
public bool esvalida_la_hora(string thetime)
{
Regex checktime = new Regex("^(?:0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$");
if (!checktime.IsMatch(thetime))
return false;
if (thetime.Trim().Length < 5)
thetime = thetime = "0" + thetime;
string hh = thetime.Substring(0, 2);
string mm = thetime.Substring(3, 2);
int hh_i, mm_i;
if ((int.TryParse(hh, out hh_i)) && (int.TryParse(mm, out mm_i)))
{
if ((hh_i >= 0 && hh_i <= 23) && (mm_i >= 0 && mm_i <= 59))
{
return true;
}
}
return false;
}
public bool IsTimeString(string ts)
{
if (ts.Length == 5 && ts.Contains(':'))
{
int h;
int m;
return int.TryParse(ts.Substring(0, 2), out h)
&& int.TryParse(ts.Substring(3, 2), out m)
&& h >= 0 && h < 24
&& m >= 0 && m < 60;
}
else
return false;
}

DateTime.Compare how to check if a date is less than 30 days old?

I'm trying to work out if an account expires in less than 30 days. Am I using DateTime Compare correctly?
if (DateTime.Compare(expiryDate, now) < 30)
{
matchFound = true;
}
Am I using DateTime Compare correctly?
No. Compare only offers information about the relative position of two dates: less, equal or greater. What you want is something like this:
if ((expiryDate - DateTime.Now).TotalDays < 30)
matchFound = true;
This subtracts two DateTimes. The result is a TimeSpan object which has a TotalDays property.
Additionally, the conditional can be written directly as:
bool matchFound = (expiryDate - DateTime.Now).TotalDays < 30;
No if needed.
Alternatively, you can avoid naked numbers by using TimeSpan.FromDays:
bool matchFound = (expiryDate - DateTime.Now) < TimeSpan.FromDays(30);
This is slightly more verbose but I generally recommend using the appropriate types, and the appropriate type in this case is a TimeSpan, not an int.
should be
matchFound = (expiryDate - DateTime.Now).TotalDays < 30;
note the total days
otherwise you'll get werid behaviour
Well I would do it like this instead:
TimeSpan diff = expiryDate - DateTime.Today;
if (diff.Days > 30)
matchFound = true;
Compare only responds with an integer indicating weather the first is earlier, same or later...
Try this instead
if ( (expiryDate - DateTime.Now ).TotalDays < 30 ) {
matchFound = true;
}
Compare returns 1, 0, -1 for greater than, equal to, less than, respectively.
You want:
if (DateTime.Compare(expiryDate, DateTime.Now.AddDays(30)) <= 0)
{
bool matchFound = true;
}
This will give you accurate result :
if ((expiryDate.Date - DateTime.Now.Date).Days < 30)
matchFound = true;
Assuming you want to assign false (if applicable) to matchtime, a simpler way of writing it would be..
matchtime = ((expiryDate - DateTime.Now).TotalDays < 30);
No, the Compare function will return either 1, 0, or -1. 0 when the two values are equal, -1 and 1 mean less than and greater than, I believe in that order, but I often mix them up.
No you are not using it correctly.
See here for details.
DateTime t1 = new DateTime(100);
DateTime t2 = new DateTime(20);
if (DateTime.Compare(t1, t2) > 0) Console.WriteLine("t1 > t2");
if (DateTime.Compare(t1, t2) == 0) Console.WriteLine("t1 == t2");
if (DateTime.Compare(t1, t2) < 0) Console.WriteLine("t1 < t2");
What you want to do is subtract the two DateTimes (expiryDate and DateTime.Now). This will return an object of type TimeSpan. The TimeSpan has a property "Days". Compare that number to 30 for your answer.
No it's not correct, try this :
DateTime expiryDate = DateTime.Now.AddDays(-31);
if (DateTime.Compare(expiryDate, DateTime.Now.AddDays(-30)) < 1)
{
matchFound = true;
}
Actually none of these answers worked for me. I solved it by doing like this:
if ((expireDate.Date - DateTime.Now).Days > -30)
{
matchFound = true;
}
When i tried doing this:
matchFound = (expiryDate - DateTime.Now).Days < 30;
Today, 2011-11-14 and my expiryDate was 2011-10-17 i got that matchFound = -28. Instead of 28. So i inversed the last check.
// this isn't set up for good processing.
//I don't know what data set has the expiration
//dates of your accounts. I assume a list.
// matchfound is a single variablethat returns true if any 1 record is expired.
bool matchFound = false;
DateTime dateOfExpiration = DateTime.Today.AddDays(-30);
List<DateTime> accountExpireDates = new List<DateTime>();
foreach (DateTime date in accountExpireDates)
{
if (DateTime.Compare(dateOfExpiration, date) != -1)
{
matchFound = true;
}
}
You can try to do like this:
var daysPassed = (DateTime.UtcNow - expiryDate).Days;
if (daysPassed > 30)
{
// ...
}
Compare is unnecessary, Days / TotalDays are unnecessary.
All you need is
if (expireDate < DateTime.Now) {
// has expired
} else {
// not expired
}
note this will work if you decide to use minutes or months or even years as your expiry criteria.

Categories