1

I have a class that presents some time range (period) that starts at Begin and ends at End:

public class Period  
{
    public DateTime Begin { get; set; }
    public DateTime End { get; set; }
}

Let's say that Begin = 01/07/2017 7:50:00 and End = 01/07/2017 12:30:00 .

What I need to get is a collection of more detailed Period objects from the base one that will consist of hourly-splitted periods - output for the example should be like this (Date part is omitted):

[0] Begin = 7:50:00, End = 7:59:59

[1] Begin = 8:00:00, End = 8:59:59

[2] Begin = 9:00:00, End = 9:59:59

[3] Begin = 10:00:00, End = 10:59:59

[4] Begin = 11:00:00, End = 11:59:59

[5] Begin = 12:00:00, End = 12:29:59

What would be the best way to do the split?

pitersmx
  • 935
  • 8
  • 27
  • 1
    Do you want to store only the time in your `Period` objects or do you still want to store `DateTime` and only display the time? – Mighty Badaboom Jul 26 '17 at 11:43
  • 2
    What have you tried? https://stackoverflow.com/questions/1847580/how-do-i-loop-through-a-date-range works with days but is easily converted to hours. – CodeCaster Jul 26 '17 at 11:44
  • I want to store DateTime, and display DateTime – pitersmx Jul 26 '17 at 11:45
  • @pitersmx You want to play `DateTime`? In your example output there is just a time... – Mighty Badaboom Jul 26 '17 at 11:45
  • @CodeCaster I will try this – pitersmx Jul 26 '17 at 11:45
  • @Mighty printing just the time is achieved by alling `DateTime.ToString("hh:MM:ss")` and is irrelevant to the rest of the problem. Remember that a DateTime represents a _moment_ in time, while a TimeSpan (which I suppose you're going to be hinting at, based on your comments) is a _range_ of time. – CodeCaster Jul 26 '17 at 11:46

3 Answers3

3
Period period = new Period();
period.Begin = new DateTime(2017, 7,1, 7,50,0);
period.End = new DateTime(2017, 7, 1, 12, 30, 0);
    
DateTime start = period.Begin;
    
List<Period> periods = new List<Period>();
while(start < period.End)
{
   DateTime end = start;
   end = end.AddMinutes(-end.Minute);
   end = end.AddSeconds(-end.Second -1);
   end = end.AddHours(1);
   if(end > period.End)
      end = period.End;

   periods.Add(new Period{Begin = start, End = end});
   start = end.AddSeconds(1);
}
    
foreach(var p in periods)
{
   Console.WriteLine($"Start: {p.Begin.ToLongTimeString()} End: 
   {p.End.ToLongTimeString()}");
}

This results in

Start: 07:50:00 End: 07:59:59
Start: 08:00:00 End: 08:59:59
Start: 09:00:00 End: 09:59:59
Start: 10:00:00 End: 10:59:59
Start: 11:00:00 End: 11:59:59
Start: 12:00:00 End: 12:30:00
Stuart
  • 3,949
  • 7
  • 29
  • 58
3

You can write a simple method that takes start and end as DateTime objects and returns a collection of periods.

static IEnumerable<Period> GetPeriods (DateTime start, DateTime end)
{
    // Create a DateTime as a pointer to increment
    DateTime ptr = start;
    while (ptr < end)
    {
        // Return a new Period, starting with the current pointer time and ending with
        //   the pointer time plus 00:59:59 (59 * 60 + 59 = 3599s)
        yield return new Period() { Start = ptr, End = ptr.AddSeconds(3599) };

        // Increment the pointer
        ptr = ptr.AddHours(1);
    }
}
Ian H.
  • 3,840
  • 4
  • 30
  • 60
2

Try this solution:

var periods = new List<Period>();
var period = new Period 
{ 
    Begin = new DateTime(2017, 07, 01, 7, 50, 0), 
    End = new DateTime(2017, 07, 01, 12, 30, 0) 
};        
var previous = period.Begin;

do
{
    var next = new Period 
    { 
        End = previous.AddSeconds(3600 - previous.Minute * 60 - 1), 
        Begin = previous 
    };
    previous = next.End.AddSeconds(1);
    if (next.End < period.End.AddSeconds(-1))
        periods.Add(next);
    else
    {
        next.End = period.End.AddSeconds(-1);
        periods.Add(next);
        break;
    }                
} while (true);

Result:

7/1/2017 7:50:00 AM - 7/1/2017 7:59:59 AM
7/1/2017 8:00:00 AM - 7/1/2017 8:59:59 AM
7/1/2017 9:00:00 AM - 7/1/2017 9:59:59 AM
7/1/2017 10:00:00 AM - 7/1/2017 10:59:59 AM
7/1/2017 11:00:00 AM - 7/1/2017 11:59:59 AM
7/1/2017 12:00:00 PM - 7/1/2017 12:29:59 PM
Slava Utesinov
  • 13,410
  • 2
  • 19
  • 26