Linux "date" command ignores leap-seconds?

D. Hugh Redelmeier hugh-pmF8o41NoarQT0dZR+AlfA at public.gmane.org
Wed Jan 16 19:59:08 UTC 2013


| From: Eric B <gyre-Ja3L+HSX0kI at public.gmane.org>

| Yes, unix timestamps do not account for leap seconds, BUT
| that is inconsistent with the 'man date' documentation.

On my Fedora 17 system, time(2) says

NOTES
       POSIX.1 defines seconds since the Epoch as a value to be interpreted as
       the number of seconds between a specified time and the Epoch, according
       to a formula for conversion from UTC equivalent to  conversion  on  the
       naive  basis that leap seconds are ignored and all years divisible by 4
       are leap years.  This value is not the same as  the  actual  number  of
       seconds  between  the  time  and the Epoch, because of leap seconds and
       because clocks are not required to be synchronised to a standard refer-
       ence.   The  intention  is that the interpretation of seconds since the
       Epoch values be consistent; see  POSIX.1  Annex  B  2.2.2  for  further
       rationale.

That leap year rule is wrong since years divisible by 100 but not 400
are not leap years.  We'll see in 2100 (if we make it past 2038).

Actually, if you look up POSIX.1 from 2004
<http://pubs.opengroup.org/onlinepubs/000095399/> and go to 4.14
"Seconds Since the Epoch", you will see that they do handle centuries
correctly.

One scary sentence:
    How any changes to the value of seconds since the Epoch are made
    to align to a desired relationship with the current actual time is
    implementation-defined. As represented in seconds since the Epoch,
    each and every day shall be accounted for by exactly 86400
    seconds.
So there is no leeway to make some days a second longer.

Anyway, here is their formula:

tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
    (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
    ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400

I'd have written that with smaller, more understandable constants:

tm_sec + 60 * (tm_min + 60 * (tm_hour + 24 * (tm_yday
	+ 365 * (tm_year-70)
	+ (tm_year-69)/4
	- (tm_year-1)/100
	+ (tm_year+299)/400)))

tm_year is years since 1900.  It would be better if it were
just "year".  Then more constants would be understandable:

tm_sec + 60 * (tm_min + 60 * (tm_hour + 24 * (tm_yday
	+ 365 * (tm_year-1970)
	+ (tm_year-1969)/4
	- (tm_year-1901)/100
	+ (tm_year-1601)/400)))

Clearly all leap years before the Epoch don't count, but ones after do.
Years that are multiples of 4 are leap years (UNLESS they are multiples
of 100 (UNLESS they are multiples of 400)).  A leap year delays the
start of subsequent years by one day.
1969 is the year after the last multiple of 4 before the epoch.
1901 is the year after the last multiple of 100 before the epoch.
1601 is the year after the last multiple of 400 before the epoch
--
The Toronto Linux Users Group.      Meetings: http://gtalug.org/
TLUG requests: Linux topics, No HTML, wrap text below 80 columns
How to UNSUBSCRIBE: http://gtalug.org/wiki/Mailing_lists





More information about the Legacy mailing list