clamchoda
clamchoda

Reputation: 4951

Looping start to end timespans overnight

hope all is swell!

I was hoping I had cracked this problem but it looks like we have ran into some errors this morning.

This is an asp.net web application, and this section is in c#. We are dynamically populating drop down lists with a openTime, closeTime, and Interval of 15 mins which are all of type TimeSpan.

TimeSpan interval = new TimeSpan(0,15,0);

    for (TimeSpan i = openTime; i <= closeTime; i = i.Add(interval))
    {

        string stringTime = i.ToString();
        ddlTime.Items.Add(new ListItem(stringTime, stringTime));
    }

This works great if the times are not over lapping midnight. Ex:

Will populate as expected:

Where this fails to work, is when the opening time starts before midnight, and the close time starts after.

I need to populate

But as you could quickly tell, the loop will not run because the openTime is not <= to closeTime in this scenario.

Simply creating another for loop to check if closeTime <= openTime will not give the desired results. I would get:

Could anyone more experienced on the subject provide what logic is required to get this working successfully.

Thanks for your time, Chris.

Upvotes: 1

Views: 2843

Answers (4)

Jon Skeet
Jon Skeet

Reputation: 1501043

It sounds like it would be better to create a DateTime for each of start and end, then loop over that until you reach the end, taking the TimeOfDay for each value:

TimeSpan interval = TimeSpan.FromMinutes(15);

for (DateTime current = openTime; current <= closeTime; current += interval)
{
    string stringTime = current.TimeOfDay.ToString();
    ddlTime.Items.Add(new ListItem(stringTime, stringTime));
}

Now if you have an open time of (say) 28th June 2012, 11pm and a close time of 29th June 2012, 2am then it will work fine.

If you get the open/close times as TimeSpans, you could always use:

// The dates don't really matter here... we just want a sample start/end
// for an opening period
DateTime open = new DateTime(2000, 1, 1) + openTimespan;
DateTime close = new DateTime(2000, 1, 1) + closeTimespan;

if (open > close)
{
    close = close.AddDays(1);
}

Of course I'd personally recommend using my own .NET date/time API, Noda Time, which has a specific LocalTime type, but that's a different matter :)

Upvotes: 4

Eric Liprandi
Eric Liprandi

Reputation: 5574

I see a couple of options:

  1. Use a DateTime structure instead to do your 15 minutes increments. Take the DateTime.TimeOfDay to as you data. (this has been suggested by others while I was writing this)
  2. Include logic that substract 24h if the TimeSpan value exceeds 24h.

One key note about #1 and the suggestions from others is the inveitable time change for Daylight saving time. You'd have to verify that your sequence does not have duplicates when we fall back or skips 1h block when we spring forward.

Does this make senses?

Regards.

Upvotes: 0

user1485585
user1485585

Reputation: 49

I think that you use TimeSpan where you should use DateTime.

Upvotes: 0

qJake
qJake

Reputation: 17139

Why are you using a TimeSpan for this, if you're concerned about dates as well?

Instead of TimeSpan.Add(interval), use DateTime.Add(new TimeSpan(0,0,interval)), and modify the rest of your code to work around a DateTime object instead of a TimeSpan object.

Upvotes: 0

Related Questions