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.
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.
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.
Related
In C++ I'm writing a function that converts time(NULL), which is all the seconds since January 1, 1970 in UTC time, to local time EST in military time format (hours:minutes:seconds). I'm honestly stumped how to mathematically do this so that the program stays accurate as time moves forward.
Also I'm well aware that there is a local time function but I'd like to build this function from the ground up. Does anyone have any advice or tips?
Also I'm well aware that there is a local time function but I'd like to build this function from the ground up. Does anyone have any advice or tips?
Why would you want to do this when there are plenty of free and well-tested packages? As mentioned in the comments, getting daylight savings time correct is non-trivial. Existing packages do just that, and they do it right, based on the IANA tzinfo database.
C options:
std::localtime(). This function uses a global variable; it is not thread safe.
localtime_r(). This is a POSIX function and is not a part of the C++ library. It does not exist on Windows.
localtime_s(). This is an optional C11 function. Even if it exists on your machine, it might not be a part of <ctime>.
C++ options:
Boost Date-Time, https://github.com/boostorg/date_time .
Howard Hinant's date-time module, https://github.com/HowardHinnant/date .
localtime() from glibc should do the job of calculating the date, provided the environment is set to the correct timezone; else use gmtime(). Building a string from the values is a separate job, see strftime() for that.
http://linux.die.net/man/3/localtime
If you want to learn about the algorithms for converting a count of days to a year/month/day triple (and back), here they are, highly optimized, explained in pains-taking detail (don't read while operating heavy machinery):
http://howardhinnant.github.io/date_algorithms.html
You should also know that most (all?) implementations of time() track an approximation of UTC called Unix Time. This count treats leap seconds simply as clock corrections to an imperfect clock. That means you can ignore the effect of leap seconds when converting Unix Time seconds to days (just divide by 86400).
For converting to EST, you have some choices (in order of increasing difficulty and accuracy):
You can ignore daylight savings time and always take the offset as -5 hours.
You can assume the current daylight savings rules, ignoring the fact that they have changed many times in the past, and will likely change again.
You can get the past and present rules from the IANA timezone database,
or your OS's local equivalent.
There are two things which you will need to consider:
1. Leap years
One extra day in a year, that is possible to calculate mathematically.
2. Leap seconds
Seconds inserted or removed as needed (so a minute can have 61 or 59 seconds).
Those are irregular and you will need a lookup table for them. Otherwise your conversion routine will not be correct.
List of them is available for example here: https://en.wikipedia.org/wiki/Leap_second
According to this struct tm documentation, the value tm_sec can be 0 - 61 and the extra range is to include leap seconds in some systems. How can I detect if there is a leap second in a system generally and in my openSUSE 13.2 machine specifically?
Leap seconds are not related to a particular system. It is even not directly an informatic problem but rather a physical one.
In a ideal world, where every clock would be perfectly accurate, there would be no reason for leap seconds. But in our restricted world, clocks tend to deviate.
Moving the system time, specially moving it backwards can cause bad things to happen. If a batch task stores the time of its last run to know which files has already been processed and because of the clock moving backwards it thinks that time is now before its last run, it will process again file which may be plain wrong.
For that reason, system developpers invented the leap seconds that allow a system to adjust its system clock (of course only slight deltas, but it is generally enough if you check you clock on a regular base) without having to move it backwards.
As noted by #Supuhstar, this is just an operating system implementation of leap seconds. But leap seconds have a true physical origin and were introduced to compensate variation between two definitions of time UTC and TAI - physically variations in earth rotation speed. I give more details on it in this other post of mine
I need to be able to convert local time to UTC on a Windows machine. I found the SystemTimeToTzSpecificLocalTime API that claims to do this, but then I read its description and found this:
The SystemTimeToTzSpecificLocalTime function may calculate the local time incorrectly under the following conditions:
The time zone uses a different UTC offset for the old and new years.
The UTC time to be converted and the calculated local time are in different years.
My first rhetorical question to MS, "How difficult is it to write a reliable API?"
And then, the actual question — how do you do it to work in 100% of the times? (And not like that API suggests.)
The answer to both your questions is that it is essentially impossible. This is one of the reasons computer science folks tend to hate dealing with local time.
Here are some examples of the confounding issues: When we jump back an hour from 2:00 to 1:00, there are two 1:30's. We also have no way to know today what the daylight savings time rules, if any, will be in ten years. Time zone boundaries are sometimes moved, so just knowing that you're in Pacific time today may not be enough to tell us what your time zone offset was 85 years ago. There is no way to know today what leap seconds may or may not be inserted in the future.
If you find yourself in a situation when it is possible, you will have to code in the specific circumstances that make those operations possible in your particular case. The operations provided are generalized and provide "usually correct" results without constraining the cases in which they can be used.
Moral: Don't use local time except for display. And even then, converting times in the past or future into local times is problematic.
Since the DST periods sometimes change in certain areas, it's hard to write something that is correct in all cases, past and future.
Nevertheless, I you need this functionality, I would suggest using the C functions (localtime, mktime, ...). I recently had a problem where the Windows function SystemTimeToTzSpecificLocalTime did not work correctly on a Citrix server (Citrix does quite some strange (but advanced) things regarding timezones), but the C functions worked correctly.
I was reading about the licensing of software and one question that came to my mind is that "how software detect the change in system time and block themselves if someone changes system time?". Since there is no other reference available(provided we don't have internet connection, otherwise we can use time servers as reference), how such software manages to do it? Are there standard algorithms or any standard libraries(C/C++) available for implementing the same. Please suggest.
You cannot assume that because the clock goes backwards, it is caused by someone trying to circumvent your licensing.
Consider, for example, the situation where someone accidentally sets the clock way into the future, then resets it to the correct time?
Crippling your software by attempting to time-restrict it is not the right thing to do. Consider making decent software instead.
Your software can regularly ask for system time (using boost::posix_time::second_clock::local_time()) and compare it with the last stored value. If you observe a significant negative difference, someone probably changed the system time.
Beware that time can be changed on a system for legitimate reasons : the computer can be moved to another timezone, the system can be using NTP and the computer clock is ticking too fast so NTP very often sets time to an earlier value or when daylight saving time change occurs.
Keep also in mind that those kind of "protection" aren't really effective in practice. If you have to store the last system date somewhere, you take the risk that someone will find where and change it to something in a far future to grant himself new licensing rights.
As far as I know, there is no elegant and reliable solution to this problem.
clock_gettime(CLOCK_MONOTONIC, &ts) gives you a timespec independent of the system time. You can use it to calc an offset between CLOCK_REALTIME and if that changes, your systemtime has changed
One strategy I have read about in the past is to create, update and check a file in a folder. You can update the date as it changes and if it goes backwards you leave it alone and can get suspicious.
However there is no 100% method of proving time shifting, in my limited experience any piracy feature usually hurts the helpdesk and your customers more than it hurts the pirates.
It is a far better strategy to get to know your trial users than to criminalise them.
You could always set the timestamp on a file to the current system time every time your application starts.
Check the time first before setting it - if it's in the future, then the clock has gone backwards since you last set it.
You can set up a timer that checks every n ticks (one tick = one (multitude of) cpu clock tick) if the system time difference is positive... Should be enough to check every second or even once a minute. Usually a timer shouldn't use up that much resources. You must make sure though that the timer uses the ticks, not the system clock...
Generally you can't detect such things consistently, since people may just reboot the machine in question.
In an ancient place I was working once an admin changed the clock because he had forgotten to renew the license for a compiler. Not really a brilliant idea. Basically the machine soon became completely unusable: NFS was messed up, make didn't work, a lot of trouble.
So my guess is that your problem is more of theoretical nature. In real life, nobody sane will probably do that.
Would you rather use a version number (that will increment) or a timestamp to check for concurrency problems?
Version number is better because no matter what format of time you use, it can still be thrown off if the server's clock is wrong or becomes wrong over time.
I have to admit, I've used a time stamp in many databases because it can serve a dual purpose of concurrency checking as well as readability for when the data was last changed. However, using a version number is really the better way to go.
I'd use a version number, particularly if the resource may ever be updated more than the resolution of your timestamps (e.g. if you're storing timestamps to a resolution of seconds, if you have multiple updates within a single second, your versioning will break).
Lieven,
I know you didn't specify SQL Server, but IF you are talking about SQL Server then the datatype TimeStamp would be the best method to use. Despite its description it doesn't really have anything to do the date and time. It's actually just a binary number which changes every time the row has been modified. Thus, if any amendments are made to the row then you kno the timestamp column will change. This has the advantage over version numbers because you, the programmer, do not have to "maintain" the version number.
Actual Date/Time timestamps need to be used more carefully as another poster referred to earlier - time differences etc.
Version number. Or if I'm using timestamp, I'll make sure it is UTC - so there is no confusion with the timezone.
If you are on Windows, I recommend to use a globally unique identifier (GUID) as the version identifier.
A timestamp (even if UTC) can make problems if the clock is set by the user. An incrementing number (if hold in memory) can make problems if the server application is restarted, or if it overflows (if it's only a 16-bit or 32-bit integer).
Version number. DateTime is not unique due some reasons, for example 'Daylight saving time' - there could be two '2 AM' h. (Ambiguous Time).
I guess that its more than enough unsigned 32 bit integer, because practically there is a ZERO probability that while saving 4,294,967,295 transaction could occur.