Creating date sequence between two given dates - fails on february - c#

Im using the following method to create a date sequence between two given dates;
public List<DateTime> dateSeq(DateTime startDate, DateTime endDate)
{
List<DateTime> allDates = new List<DateTime>();
for (DateTime date = startDate; date <= endDate; date = date.AddMonths(1))
allDates.Add(date);
return allDates;
}
Creating a date sequence while incrementing 1 month, when the given date for example are:
startDate: 2017-01-01
endDate: 2017-05-01
the sequence i get is fine:
2017-01-01
2017-02-01
2017-03-01
2017-04-01
2017-05-01
But when the given dates are:
startDate: 2017-01-31
endDate: 2017-05-31
The sequence i get fail when passing february setting the rest of the months sequence on the 28th day:
2017-01-31
2017-02-28
2017-03-28
2017-04-28
2017-05-28
Can someone please explain why is that?

Because the 2017-02-31 doesn't exist and 2017-02-28.AddMonth(1) results into 2017-03-28 which is correct.
I think you're looking for a approach which maintains the initial start day
public IEnumerable<DateTime> dateSeq(DateTime startDate, DateTime endDate)
{
int temp = 0;
while (startDate.AddMonths(temp) <= endDate)
yield return startDate.AddMonths(temp++);
}
https://dotnetfiddle.net/Mz7yFh

Related

How to get past week dates from a list of dates in C#?

In My DB I have a dates like this:
01-03-2022 00:00:00
07-03-2022 00:00:00
05-03-2022 00:00:00
012-03-2022 00:00:00
013-03-2022 00:00:00
014-03-2022 00:00:00
after every week on Monday, I need past 1 week dates to be fetched
I am iterating through dates like this:
foreach(var item in model.dates)
{
// item.Date has all dates
// I don't know how to get dates here
}
I want to fetch only those dates, How can I do that?
if (DateTime.Today.DayOfWeek == DayOfWeek.Monday)
{
DateTime weekStart = DateTime.Today.AddDays(-7);
DateTime weekEnd = DateTime.Today.AddDays(-1);
var result = model.Dates.Where(x => weekStart <= x && weekEnd >= x);
}

How do I handle datetime with no day in a linq comparison?

I am given two dates as strings like this:
Beginning month: 10
Beginning year: 2010
Ending month: 01
Ending Year 2020
I want to query my entity and get everything that is equal or between these ranges.
So, I want everything from 10/2010 to 01/2020.
I have this code and I got stuck on how to convert the date correctly and the comparison:
dollartotals = (from x in se.AchBatches
where x.CompanyCode == company &&
DbFunctions.TruncateTime(x.DateTimeSubmitted) >=
// stuck here
select x.DollarTotal).Sum();
How do I handle the individual month/year strings and make a date comparison without a day?
Thanks for any assistance!
You want to check against the actual datetime submitted, not a truncated version of it.
The key is to build actual datetimes in advance, then just do a regular date window check.
Assume you have four strings as listed in your question:
//you might use TryConvert or a Try block here to validate your string data...
int beginYear = Integer.Convert(strBeginYear);
int beginMonth = Integer.Convert(strBeginMonth);
int endYear = Integer.Convert(strEndYear);
int endMonth = Integer.Convert(strEndMonth);
DateTime start = new DateTime(beginYear, beginMonth, 1);
DateTime endLimit = new DateTime(endYear, endMonth, 1).AddMonths(1);
dollartotals = (from x in se.AchBatches
where x.CompanyCode == company &&
x.DateTimeSubmitted >= start &&
x.DateTimeSubmitted < endLimit
select x.DollarTotal).Sum();
I want everything from 10/2010 to 01/2020.
Not sure if you want a DateTime sequence with every Tick between those dates, or every second, or every Day. Let's assume you want every Day: All Days from startDate.Date until and inclusive endDate.Date.
I use StartDate.Date, so if StartDate is 2020-02-05 13:20:14, then you still get February 5th 2020 at 00:00:00
IEnumerable<DateTime> GetDateRange(DateTime startDate, DateTime endDate)
{
DateTime lastDate = endDate.Date;
DateTime date = startDate.Date;
while (date <= lastDate)
{
yield return date;
date = date.AddDays(+1);
}
}
Usage:
var allDaysOfFebruary2020 = GetDateRange(new DateTime(2020, 01, 01),
new DateTime(2020, 02, 29));
You'll get the sequence from 1st February 2020 until and inclusive 29th February 2020.

Timespan between (2) other Timespan when adding / subtracting minutes C#

Everything works with the exception if I pass in "15 minutes". I receive no errors, it's just that my where clause isn't working 100%. This is b/c I pass in time in 15 minute intervals.
Example:
Object 1 has a time of 00:20 (12:20 am) (24hr format)
Object 2 has a time of 02:15 (02:15 am) (24hr format)
The parsedTime param is a javascript 24hr format time - in this example is comes in as "00:15".
The problem is when I subtract the -30 minutes from the parsedTime, it puts it at 23:45, and therefore never gets the "00:20".
LINQ query
DateTime parsedTime = DateTime.ParseExact(time, "HH:mm", CultureInfo.InvariantCulture);
var activities = objects
.Where(x => (x.GetValue<DateTime>("startTime").TimeOfDay
>= parsedTime.AddMinutes(-30).TimeOfDay
&& x.GetValue<DateTime>("startTime").TimeOfDay
<= parsedTime.AddMinutes(30).TimeOfDay))
.ToList();
You just want to see if they're within 30 minutes of each other, right? Try using actual timespans
DateTime startTime;
DateTime parsedTime;
TimeSpan difference = startTime - parsedTime;
return difference.TotalMinutes < 30 && difference.TotalMinutes > -30;
It sounds like you also need to handle time ranges that could span across midnight, as in the 30 minutes that exists between "23:45" and "00:15". Here's how you can do that:
public static TimeSpan GetTimeDifference(string startTimeOfDay, string endTimeOfDay)
{
DateTime startDateTime = DateTime.ParseExact(startTimeOfDay, "HH:mm",
CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault);
DateTime endDateTime = DateTime.ParseExact(endTimeOfDay, "HH:mm",
CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault);
if (endDateTime >= startDateTime)
{
// values do not cross over midnight
return endDateTime - startDateTime;
}
else
{
// values cross over midnight
return endDateTime - startDateTime + TimeSpan.FromHours(24);
}
}
Or if you prefer something smaller:
public static int GetMinutesDifference(string startTimeOfDay, string endTimeOfDay)
{
DateTime startDateTime = DateTime.ParseExact(startTimeOfDay, "HH:mm",
CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault);
DateTime endDateTime = DateTime.ParseExact(endTimeOfDay, "HH:mm",
CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault);
return (((int)(endDateTime - startDateTime).TotalMinutes + 1440) % 1440);
}

Simple way to get days given start and end dates

Is there a rapid and simple way to obtain a List<DateTime> given start and end dates?
I obviously know that I can achieve this by a loop, but I'm wondering if there is a smarter method using Linq or some other utility.
NOTE I need to get a DateTime instance for every single day between two given dates.
Iterator blocks are great for this.
I see no reason not to use a for loop here for this. You need to perform some operator for each date, given that you have that many outputs, no method will have any better asymptotic complexity.
public static IEnumerable<DateTime> GetDates(DateTime startDate, DateTime endDate
, TimeSpan interval)
{
for (DateTime date = startDate; date < endDate; date.Add(interval))
{
yield return date;
}
}
You can add an overload for a fixed interval as well:
public static IEnumerable<DateTime> GetDays(DateTime startDate, DateTime endDate)
{
return GetDates(startDate, endDate, TimeSpan.FromDays(1));
}
You can do like this to get a list from startDate to endDate:
List<DateTime> dates =
Enumerable.Range(0, (int)((endDate - startDate).TotalDays) + 1)
.Select(n => startDate.AddDays(n))
.ToList();
Assuming that you want daily granularity, and include the start and end dates:
var start = new DateTime(2012, 01, 01);
var end = new DateTime(2013, 01, 01);
var daysInBetween = Enumerable.Range(0, (int) (end - start).TotalDays + 1)
.Select(value => start.AddDays(value));
Lazy evaluated query might look like:
//inclusive start and inclusive end
public IEnumerable<DateTime> DateSequence(DateTime start, TimeSpan interval, DateTime end)
{
DateTime current = start;
while(current <= end)
{
yield return current;
current = current.Add(interval);
}
}
Now you can simply use it like following. To get every day set interval to TimeSpan.FromDays(1)
var start = DateTime.Now;
var end = DateTime.Now.AddDays(7);
var interval = TimeSpan.FromDays(1);
var sequence = DateSequence(start, interval, end);
//LinqPad specific call
sequence.Dump();
prints:
1/14/2013 5:34:57 PM
1/15/2013 5:34:57 PM
1/16/2013 5:34:57 PM
1/17/2013 5:34:57 PM
1/18/2013 5:34:57 PM
1/19/2013 5:34:57 PM
1/20/2013 5:34:57 PM

C# Add TimeSpan to DateTime by considering BusinessDays

I have a collection of dates that are business days and I have a Start Date. When I add a TimeSpan to the Start Date DateTime I have to ensure that when adding the days in TimeSpan, I skip over holidays. Any suggestions on how I can do this?
You add the timespan as it is. When that is done, you iterate search for dates in your collection that falls between the original date and the new date. For each time you encounter for each hit you add another day to the new date, and repeat until you are through your collection of dates. This can be optimized if your datecollection is sorted.
You need to take into account how many non-business days there are in any added date range.
In a 20 day range, there may be 6 non-business days.
You can't just add this number of days to the last day because the new date range may contain non-business days too. You have to add the days, and then figure out how many of those days you've added are also holidays:
Here's some non-tested pcode
Add Timespan to date (DateIn,timespan)
finalDateTime = (fromDate + timespan)
fromDate = DateIn.date
toDate = finalDateTime.date
repeat
iDays = GetHolidaysBetween (fromDate, toDate)
finalDateTime = (finalDateTime + iDays)
fromDate = (toDate+1)
toDate = (toDate+iDays)
until (iDays=0)
return finalDateTime
end_function
What about something like this?
public DateTime AddBusinessDays(List<DateTime> businessDays, DateTime startDate, TimeSpan span)
{
// Add the initial timespan
DateTime endDate = startDate.Add(span);
// Calculate the number of holidays by taking off the number of business days during the period
int noOfHolidays = span.Days - businessDays.Where(d => d >= startDate && d <= endDate).Count();
// Add the no. of holidays found
endDate.AddDays(noOfHolidays);
// Skip the end date if it lands on a holiday
while (businessDays.Contains(endDate))
endDate = endDate.AddDays(1);
return endDate;
}

Categories

Resources