Search code examples
c#datedatetimetimestampdate-range

Effecient way to split range of DateTimes


I have two DateTime's, X and Y. Where X always occurred before Y. They might be milliseconds to years apart from each other. How can I in C# efficiently split them up on date end (00:00)?

E.g (24h clock)

X: 2010-01-01 14:00
Y: 2010-01-02 11:00
Result
2010-01-01 14:00 - 2010-01-02 00:00
2010-01-02 00:00 - 2010-01-02 11:00

-

X: 2010-01-01 05:00
Y: 2010-01-03 18:00
Result
2010-01-01 05:00 - 2010-01-02 00:00
2010-01-02 00:00 - 2010-01-03 00:00
2010-01-03 00:00 - 2010-01-03 18:00

-

X: 2010-01-01 05:00
Y: 2010-01-01 06:00
Result
2010-01-01 05:00 - 2010-01-01 06:00

-

X: 2010-01-01 02:00
Y: 2010-01-04 22:00
Result
2010-01-01 02:00 - 2010-01-02 00:00
2010-01-02 00:00 - 2010-01-03 00:00
2010-01-03 00:00 - 2010-01-04 00:00
2010-01-04 00:00 - 2010-01-04 22:00

Solution

  • Here's a method that will do the partitioning that you want. Note there is no checking to make sure the initial start is before end.

    public IEnumerable<(DateTime Start, DateTime End)> DaySplit(DateTime start, DateTime end)
    {
        var partition = start.AddDays(1).Date;
        while(partition < end)
        {
            yield return (start, partition);
            start = partition;
            partition = start.AddDays(1);
        }
    
        yield return (start, end);
    }
    

    Note that will create the ranges lazily so you'll have to iterate it to get the values either in a foreach loop or by calling ToList or ToArray on it. Additionally it uses value tuples from C# 7. You can instead use Tuple<DateTime, DateTime> or a custom type instead.