dlanod
dlanod

Reputation: 8990

Manipulating times logically with respects to daylight savings time

Is there a way to logically (not absolutely) add a time period to a local time and get a valid local time in the future?

For example, adding one day to 11 am on day 1 becomes 11 am on day 2 even if there's a daylight savings change (+/- one hour) in the meantime? If the time doesn't exist, it could return an error or the next valid time.

C++ standard mechanisms, Windows API functions, STL and/or Boost classes are all fine.

Upvotes: 1

Views: 540

Answers (2)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241563

If you're starting with a local time such as 2013-07-02 18:30:00 and you just want to go to the next calendar day at the same time, then despite the suggestions of others - you really don't want to involve UTC.

You are working in terms of calendar time. UTC is for measuring instantaneous time. Calendar time can have discontinuities for DST changes, but instantaneous time does not.

When you add a day to instantaneous time, you are always adding exactly 24 hours. But when you add a day to calendar time, you are advancing the calendar by one day position. That is subtle, but distinctly different. A calendar day might have 23, 24, or 25 actual hours to it.

When it comes to discontinuities, you will need to deal with the "spring-forward" transition, when the clocks skip an hour. If you add a day and end up in this gap, you would be referring to a time that doesn't exist on the calendar. You need to decide what you want to have happen in this case. Should it advance to the next possible time? Or should it error? Or perhaps you will add one more hour in this case. It's up to you.

The other discontinuity is the "fall-back" transition, when the clocks roll back an hour. There may be two actual instants that this single calendar position could refer to - but since you were only interested in the calendar time, then that shouldn't affect you directly. If you do want to know what instant it maps to, then you would again need to make a decision - perhaps involving some business logic or asking the user via UI.

In order to know where the discontinuities are, you will need a time zone database. The IANA database is the defacto standard.

For C++, you should look into using Boost's Date and Time support. They do use the standard database (aka "ZoneInfo"), and discuss using it here. You probably want to use a local_time.

If at all possible, stay away from POSIX time zone settings like PST8DST, while Boost supports them, they are cryptic and generally difficult to use internationally. The IANA time zones have lookup keys consisting of area and location, such as America/New_York or Europe/London.

Also look in Boost at local_time::ambiguous_result and local_time::time_label_invalid. Those will tell you if you are in a discontinuity.

I will also say that (IMHO), working with local date times, time zone, DST, etc. is much more complex in C++ than in any other language. There are great solutions for PHP, Python, .Net, Ruby, and others. Boost probably has the most comprehensive date/time implementation for C++, but it is no where near as simple as a library like Noda Time for .Net

UPDATE

I've come to realize that Boost's support for IANA/Olson time zones is flawed. Their time zone data file strips away the rich history of the IANA/Olson time zone database - which essentially recreates all of the problems of POSIX time zones that I described in the timezone tag wiki. Therefore, I no longer recommend using Boost for time zone conversion.

Instead, consider ICU, or the time zone functions of the GNU C library (as described here) - both of which use the IANA/Olson time zone data in its entirety.

Upvotes: 1

paddy
paddy

Reputation: 63481

It sort of depends on your semantics.

If you are interested in what the local time might be in exactly half a day, then yes: you convert to UTC, add half a day, and convert back to local time.

On the other hand, if you operate primarily on local times (we do this in electricity load forecasting, for example), you might go the other way, ie 'how many hours away is our half-day future event?': you treat the local time as if it were UTC, add half a day, then treat that as a local time and convert back to UTC to do sanity checks - you have to be aware that some local times don't exist, and some local times are ambiguous.

Upvotes: 1

Related Questions