<?xml version="1.0" encoding="UTF-8"?>
<codes type="array">
  <code>
    <code>public static class MidnightPartitioner
    {
        public struct SchedulePartition
        {
            public DateTime Start { get; set; }
            public DateTime End { get; set; }
        }
        
        /// &lt;summary&gt;
        /// Splits a starting and ending DateTime range into
        /// SchedulePartition objects. Each SchedulePartition
        /// represents a span of time spent in a specific date.
        /// &lt;/summary&gt;
        /// &lt;param name="scheduleStart"&gt;&lt;/param&gt;
        /// &lt;param name="scheduleEnd"&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static IEnumerable&lt;SchedulePartition&gt; Break(DateTime scheduleStart, DateTime scheduleEnd)
        {
            List&lt;SchedulePartition&gt; dayBlocks = new List&lt;SchedulePartition&gt;();
            if (scheduleStart &lt;= scheduleEnd)
            {
                DateTime tomorrow = scheduleStart.Date.AddDays(1);      // Determine when tomorrow is.
                if (tomorrow &lt; scheduleEnd) /* Schedule ends after tomorrow */
                {
                    // Calculates the time spent spent in the scheduleStart date.
                    TimeSpan timeSpentInScheduleStartDate = tomorrow.Subtract(scheduleStart);
                    // Calculates the time spent in the day after the schedule start date
                    TimeSpan timeSpentInDayAfterScheudleStart = scheduleEnd.Subtract(tomorrow);
                    dayBlocks.Add(
                        new SchedulePartition { Start = scheduleStart, End = scheduleStart.Add(timeSpentInScheduleStartDate) }
                        );
                    if (timeSpentInDayAfterScheudleStart.TotalDays &gt; 1)
                    {
                        dayBlocks.AddRange(
                            Break(tomorrow, scheduleEnd)
                            );
                    }
                    else
                    {
                        dayBlocks.Add(
                            new SchedulePartition { Start = tomorrow, End = tomorrow.Add(timeSpentInDayAfterScheudleStart) }
                            );
                    }
                }
                else
                {
                    /* Schedule ends before tomorrow. Cannot be partitioned around midnight.
                     * Return the uncut schedule as a SchedulePartition */
                    return new[]
                    {
                        new SchedulePartition
                        {
                            Start = scheduleStart,
                            End = scheduleEnd
                        }
                    };
                }
            }
            else
                throw new ArgumentException("Chronological error with scheduleStart and scheduleEnd arguments");
            return dayBlocks;
        }
    }</code>
    <comment>I have this little class called MidnightPartitioner which I use to split schedules (represented by a DateTime starting and ending) around midnight. I'm pretty sure my logic is correct in my code, but I have the feeling there is a cleaner and more concise way to split my schedule start and end times into 'blocks' around midnight. Any ideas on how I can clean up this code would be appreciated.

Example:

If scheduleStart and scheduleEnd spans 3 days, then the amount of time spent in each day would make give us 3 SchedulePartition objects. Thus, the TimeSpan length of all schedule partition objects should equal the TimeSpan of scheduleEnd.Subtract(scheduleStart)</comment>
    <created-at type="datetime">2009-07-01T14:42:21+00:00</created-at>
    <id type="integer">942</id>
    <language>C#</language>
    <permalink>split-datetime-range-around-midnights</permalink>
    <refactors-count type="integer">3</refactors-count>
    <title>Split DateTime Range Around Midnights</title>
    <trackback-url></trackback-url>
    <updated-at type="datetime">2009-07-07T18:46:33+00:00</updated-at>
    <user-id type="integer">1570</user-id>
    <user>
      <id type="integer">1570</id>
      <identity-url>http://artanis0.myopenid.com</identity-url>
      <name>MRuston</name>
      <rating type="float">0.0</rating>
      <refactors-count type="integer">1</refactors-count>
      <website></website>
    </user>
  </code>
</codes>
