3

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?

4 Answers4

3

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:

David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • 1
    +1 for Howard Hinnant's date module. Check out [his CPPCon presentation on YouTube](https://youtu.be/tzyGjOm8AKo) describing its usage. – Matt Johnson-Pint Jan 28 '16 at 16:38
2

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

Murphy
  • 3,827
  • 4
  • 21
  • 35
1

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):

  1. You can ignore daylight savings time and always take the offset as -5 hours.

  2. 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.

  3. You can get the past and present rules from the IANA timezone database, or your OS's local equivalent.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
0

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

EmDroid
  • 5,918
  • 18
  • 18
  • 1
    I believe, in Unix Time leap seconds do not affect flow of the time: either single timepoint happens twice or is skipped. So midnight + 60*60*24 seconds is always midnight. You need leap time table only if you need to know _exactly_ how many seconds are there between two timepoints. – Revolver_Ocelot Jan 27 '16 at 18:35
  • He can use the difftime function. – hookenz Jan 27 '16 at 19:58
  • Computer clocks aren't particularly accurate. That's why we have the Network Time Protocol. Shortly after a leap second happens, a modern computer connected to the internet will see that time has somehow changed and update its system-wide "seconds since 00:00 1 Jan 1970 UTC" counter. Bottom line: One does not need to account for leap seconds. – David Hammen Jan 28 '16 at 16:43