Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

linq query to split a time interval into daily batches with part days at start and end

Tags:

c#

linq

Given the following dates

2/19/2014 12:16:28 PM (Ticks: 635284091223116843)
2/23/2014 9:10:33 AM (Ticks: 635287435672549275)

What is the easiest way to obtain a list of intervals split into daily batches so that the first batch starts at 12:16:28 to midnight. Then full day intervals until start of day 2/23/2014 which is then the last part day until the exact end time.

I need to split this period into daily intervals. The interval needs to work when start and end fall on the same day.

My Naive initial attempt looks like this:

Algorithm:

I am sure this can be done with a neat elegant linq query, rather than my cludgy first attempt.

var current = start;
while (current.Ticks < end.AddDays(-1).Ticks)
{
    new [] { current, current.EndOfDay() }.Dump("interval");
    current = current.AddDays(1).StartOfDay();
}
if (end > current)
    new[] { current, end }.Dump("interval");

Result:

2/19/2014 12:28:19 PM 
2/19/2014 11:59:59 PM 

2/20/2014 12:00:00 AM 
2/20/2014 11:59:59 PM 

2/21/2014 12:00:00 AM 
2/21/2014 11:59:59 PM 

2/22/2014 12:00:00 AM 
2/22/2014 11:59:59 PM 

2/23/2014 12:00:00 AM 
2/23/2014 09:22:24 AM

Extension Methods:

public static DateTime StartOfDay(this DateTime date)
{
    return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, 0);
}
public static DateTime EndOfDay(this DateTime date)
{
    return new DateTime(date.Year, date.Month, date.Day, 23, 59, 59, 999);
}
like image 562
Jim Avatar asked Jan 18 '26 05:01

Jim


1 Answers

    {
        var dStart = new DateTime(2015,2,12,1,15,0);            
        var dEnd = new DateTime(2015,2,12,1,15,0);
        var x = Enumerable.Range(0, (dEnd.Date-dStart.Date).Days + 1)
                          .Select(c=>Tuple.Create(
                                     Max(dStart.Date.AddDays(c),dStart), 
                                     Min(dStart.Date.AddDays(c+1).AddMilliseconds(-1), dEnd)
                                 ));

    }

    private static DateTime Min(DateTime a, DateTime b)
    {
        if (a>b)
            return b;
        return a;
    }

    private static DateTime Max(DateTime a, DateTime b)
    {
        if (a<b)
            return b;
        return a;
    }

with input

var dStart = new DateTime(2015,2,19,11,15,0);           
var dEnd = new DateTime(2015,2,23,9,15,0);

the output of string.Join(Environment.NewLine, x) is

(2/19/2015 11:15:00 AM, 2/19/2015 11:59:59 PM)
(2/20/2015 12:00:00 AM, 2/20/2015 11:59:59 PM)
(2/21/2015 12:00:00 AM, 2/21/2015 11:59:59 PM)
(2/22/2015 12:00:00 AM, 2/22/2015 11:59:59 PM)
(2/23/2015 12:00:00 AM, 2/23/2015 9:15:00 AM)
like image 193
ASh Avatar answered Jan 20 '26 19:01

ASh