Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one compute a time_t for the epoch in pure ISO C?

Tags:

c

timezone

time

Using nothing but the C standard library (plain ISO C, no POSIX, and thus no assumption that time_t is represented in "seconds since the epoch"), what is the simplest way to get a time_t value corresponding to 01 Jan 1970 00:00:00 UTC?

The UTC part is the key; otherwise, just using mktime on a properly initialized struct tm would trivially solve the problem.

Alternatively (this is actually the "point" of the question), how does one portably determine the number of POSIX seconds between a given time_t value, e.g. the current time obtained via time(0), and the epoch? By "POSIX seconds" I mean the definition used in POSIX's "Seconds Since the Epoch" which does not use leap seconds. If this sounds too complicated, just go back to the question as originally stated in the first paragraph and assume the epoch is representable in time_t.

like image 917
R.. GitHub STOP HELPING ICE Avatar asked Dec 19 '12 17:12

R.. GitHub STOP HELPING ICE


1 Answers

Here's an entry for a way to do it, "simplest" if nobody beats it:

  • call mktime on a struct tm for 02 Jan 1970 00:00:00
  • call mktime on a struct tm for 31 Dec 1969 00:00:00. This could reasonably return -1, in which case treat it as 0.
  • Binary search between the two for a value of time_t that, when passed to gmtime, results in 01 Jan 1970 00:00:00

Assumes that no local time is ever more than 24 hours different from UTC, which I'm pretty sure is a fact. We could widen the boundaries if necessary, in extremis we could search between 0 and time(0).

The binary search could be improved on, for example by interpolation. But who knows, maybe some crazy time zone (or broken tzinfo data) could cause a daylight savings change in December/January. I doubt that happened for any real time zone. But it's not forbidden by the C standard, only by common sense.

If it wasn't for that, I think we could calculate based on gmtime(mktime(01 Jan)) (to get the time zone) and a comparison of 01 Jan 1970 00:00:00 vs 01 Jan 1970 00:00:01 (to get the precision of time_t).

like image 98
Steve Jessop Avatar answered Sep 26 '22 01:09

Steve Jessop