Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Inconsistancy between mktime and system time accross leapsecond

0 views
Skip to first unread message

M. Warner Losh

unread,
Aug 6, 2005, 2:16:20 AM8/6/05
to stan...@freebsd.org
During a leap second on a system controlled by ntp, the last second of
the month is replayed. This keeps the system time in the right day
(the leap second is considered to be part of the last day of the
month, not the first of the next) and has a few other nice properties.
If one gets the time of day during the leap second with ntp_gettime,
the time state will indicate that a leap second is in progress and
that the TAI offset is now one larger than before. If we look at the
TAI offset plus the system time, we get a conversion from the UTC
second that time_t represents to the TAI time.

mktime, however, when fed a leap second says that it is the first
second of the first day of the month (which is the second that gets
repeated). posix is silent on what, exactly, to do with leap seconds.
It gives a formula that seems to support mktime's return value.
However, since leap seconds are undefined in posix's time_t epoch, a
case can be made for other values. In addition, there's a one second
jump if one tries to compute TAI time from UTC time_t time for the
leap second. These flaws, while trivial to many programs, matter to
some folks.

I'd like to resolve this ambigutiy. Since ntp isn't going to change
how it handles leap seconds, and since I believe that to be the right
way to deal with leap seconds since it preserves the right day of week
and doesn't kick of jobs too early, etc, I'd like to change mktime's
behavior to match system time's during the leap second.

Comments on the following patch?

Warner

Index: localtime.c
===================================================================
RCS file: /cache/ncvs/src/lib/libc/stdtime/localtime.c,v
retrieving revision 1.40
diff -u -r1.40 localtime.c
--- localtime.c 24 Aug 2004 00:15:37 -0000 1.40
+++ localtime.c 5 Aug 2005 22:57:21 -0000
@@ -1506,7 +1506,20 @@
saved_seconds = yourtm.tm_sec;
yourtm.tm_sec = SECSPERMIN - 1;
} else {
- saved_seconds = yourtm.tm_sec;
+ /*
+ ** Posix time_t is specified such that leap seconds
+ ** are swizzled into the time. As such, the last
+ ** second of the day is repeated. Without this adjustment,
+ ** we incorrectly repeat the first second of the following
+ ** day. To be pedantically correct, we should look up to
+ ** see if this is really a leap second or not.
+ */
+ if (yourtm.tm_hour == HOURSPERDAY - 1 &&
+ yourtm.tm_min == MINSPERHOUR - 1 &&
+ yourtm.tm_sec == SECSPERMIN)
+ saved_seconds = SECSPERMIN - 1;
+ else
+ saved_seconds = yourtm.tm_sec;
yourtm.tm_sec = 0;
}
/*

M. Warner Losh

unread,
Aug 6, 2005, 2:35:12 AM8/6/05
to stan...@freebsd.org
In message: <20050806.00162...@bsdimp.com>
"M. Warner Losh" <i...@bsdimp.com> writes:
: Comments on the following patch?

A common practice is to add tm_sec += 20 to get the time 20 seconds in
the future. This patch breaks that for non-leap seconds. I'll update
the patch to fix that properly.

Warner

Garrett Wollman

unread,
Aug 6, 2005, 12:59:27 PM8/6/05
to M. Warner Losh, stan...@freebsd.org
<<On Sat, 06 Aug 2005 00:16:20 -0600 (MDT), "M. Warner Losh" <i...@bsdimp.com> said:

> mktime, however, when fed a leap second says that it is the first
> second of the first day of the month (which is the second that gets
> repeated). posix is silent on what, exactly, to do with leap
> seconds.

Actually, POSIX is not silent. It says they are to be ignored. From
XBD section 4.4:

As represented in seconds since the Epoch, each and every day
shall be accounted for by exactly 86400 seconds.

You can model this as the POSIX epoch advancing by one second for
every leap second inserted (and similarly for deletions).

> It gives a formula that seems to support mktime's return value.
> However, since leap seconds are undefined in posix's time_t epoch, a
> case can be made for other values.

A case has been made, which has repeatedly been rejected by the POSIX
committee. If you specify 23:59:60Z, a POSIX implementation *must*
normalize it to 00:00:00 the following day. If you don't care about
POSIX compliance, then the code already supports what you want, by
encoding the leap-second tables into the timezone files. See
src/share/zoneinfo/Makefile. You'll want to add calls to time2posix()
and posix2time() to ntpd to adjust kernel times appropriately.

-GAWollman

Garrett Wollman

unread,
Aug 6, 2005, 3:12:49 PM8/6/05
to M. Warner Losh, stan...@freebsd.org
<<On Sat, 06 Aug 2005 13:00:24 -0600 (MDT), "M. Warner Losh" <i...@bsdimp.com> said:

> You are right that all other :60 situations should normalize to the
> next day. There are many things that depend on this behavir.
> However, :60 means 'the next second after :59'. For all non-leap
> second days, this is the first second of the next day. For leap
> second days, this is the repated second...

In POSIX, there are no "leap second days" and "non-leap second days".
The behavior of mktime() must be equivalent to the formula in XBD
section 4.4. The Standard is clear and conforming implementations
must implement the behavior described:

# The relationship between the tm structure (defined in the <time.h>
# header) and the time in seconds since the Epoch is that the result
# shall be as specified in the expression given in the definition of
# seconds since the Epoch (see the Base Definitions volume of IEEE Std
# 1003.1-2001, Section 4.14, Seconds Since the Epoch) corrected for
# timezone and any seasonal time adjustments, where the names in the
# structure and in the expression correspond.

(XSH page 765 in the original edition of the Standard.)

The Standard may be wrong, but the committee has been unable to make
progress on this issue in more than a decade of sometimes-contentious
debate, so the existing language stands.

-GAWollman

M. Warner Losh

unread,
Aug 6, 2005, 3:00:24 PM8/6/05
to wol...@csail.mit.edu, stan...@freebsd.org
In message: <17140.60527....@khavrinen.csail.mit.edu>
Garrett Wollman <wol...@csail.mit.edu> writes:

: <<On Sat, 06 Aug 2005 00:16:20 -0600 (MDT), "M. Warner Losh" <i...@bsdimp.com> said:
:
: > mktime, however, when fed a leap second says that it is the first
: > second of the first day of the month (which is the second that gets
: > repeated). posix is silent on what, exactly, to do with leap
: > seconds.
:
: Actually, POSIX is not silent. It says they are to be ignored. From
: XBD section 4.4:
:
: As represented in seconds since the Epoch, each and every day
: shall be accounted for by exactly 86400 seconds.
:
: You can model this as the POSIX epoch advancing by one second for
: every leap second inserted (and similarly for deletions).

Yes. I understand that. The inserted second is the last second of
the day on the day it is inserted. I understand that time_t will be
ambiguous at that time.

: > It gives a formula that seems to support mktime's return value.


: > However, since leap seconds are undefined in posix's time_t epoch, a
: > case can be made for other values.
:
: A case has been made, which has repeatedly been rejected by the POSIX
: committee. If you specify 23:59:60Z, a POSIX implementation *must*
: normalize it to 00:00:00 the following day. If you don't care about
: POSIX compliance, then the code already supports what you want, by
: encoding the leap-second tables into the timezone files. See
: src/share/zoneinfo/Makefile. You'll want to add calls to time2posix()
: and posix2time() to ntpd to adjust kernel times appropriately.

Can you site where this is in the standard or in some followup doc? I
can't find it at all.

I'm not talking about turning on code to keep the leapseconds in the
time_t value. I'm talking about making mktime() return the same value
that the kernel returns during the leap second.

Specifically, the sequence of time at the end of this year will be, on
systems whose time is steered by ntpd or equivalent, will be

time_t UTC time TAI offset TAI since 1970

1136098798 23:59:58 0 (or 32) 1136098830
1136098799 23:59:59 0 (or 32) 1136098831
1136098799 23:59:60 1 (or 33) 1136098832
1136098800 00:00:00 1 (or 33) 1136098833
1136098801 00:00:01 1 (or 33) 1136098834

Since the system time will be 1136098799 during the leap second,
mktime() of that time should also be 1136098799 for that exact
second. Also, to get the TAI time correctrly, the above sequence has
to happen in that order.

You are right that all other :60 situations should normalize to the
next day. There are many things that depend on this behavir.
However, :60 means 'the next second after :59'. For all non-leap
second days, this is the first second of the next day. For leap
second days, this is the repated second...

Who said leap seconds were easy...

Warner

M. Warner Losh

unread,
Aug 6, 2005, 8:28:32 PM8/6/05
to wol...@csail.mit.edu, stan...@freebsd.org
In message: <17141.2993.3...@khavrinen.csail.mit.edu>
Garrett Wollman <wol...@csail.mit.edu> writes:
: The Standard may be wrong, but the committee has been unable to make

: progress on this issue in more than a decade of sometimes-contentious
: debate, so the existing language stands.

So are we therefore precluded from fixing this obvious bug? This is
stupid and wrong.

Warner

Garrett Wollman

unread,
Aug 6, 2005, 9:07:45 PM8/6/05
to M. Warner Losh, stan...@freebsd.org
<<On Sat, 06 Aug 2005 18:28:32 -0600 (MDT), "M. Warner Losh" <i...@bsdimp.com> said:

> So are we therefore precluded from fixing this obvious bug? This is
> stupid and wrong.

Committee membership is open to all. The 1003.1 standard is up for
review next year; you are welcome to try to persuade the sponsors
(IEEE, ISO, Open Group) that the current situation is unacceptable.
I did my part in 2001.

The reason this discussion always gets ratholed is that you'll find
all sorts of people with other agendas piling on to get the time
interfaces "fixed" for their particular concerns. Never mind that the
domain of time_t has no logical connection to the leap-second botch;
there are people who will insist that the latter cannot be fixed
unless the committee simultaneously "fixes" the Y2038 problem. Other
people will want to get reentrant timezone handling. Thankfully,
Bernstein is not on the committee (that I've seen) so at least there's
nobody insisting that the only possible correct approach is to import
libtai.

-GAWollman

M. Warner Losh

unread,
Aug 6, 2005, 9:18:37 PM8/6/05
to wol...@csail.mit.edu, stan...@freebsd.org
In message: <17141.24289....@khavrinen.csail.mit.edu>
Garrett Wollman <wol...@csail.mit.edu> writes:

: <<On Sat, 06 Aug 2005 18:28:32 -0600 (MDT), "M. Warner Losh" <i...@bsdimp.com> said:
:
: > So are we therefore precluded from fixing this obvious bug? This is
: > stupid and wrong.
:
: Committee membership is open to all. The 1003.1 standard is up for
: review next year; you are welcome to try to persuade the sponsors
: (IEEE, ISO, Open Group) that the current situation is unacceptable.
: I did my part in 2001.

OK.

: The reason this discussion always gets ratholed is that you'll find


: all sorts of people with other agendas piling on to get the time
: interfaces "fixed" for their particular concerns. Never mind that the
: domain of time_t has no logical connection to the leap-second botch;
: there are people who will insist that the latter cannot be fixed
: unless the committee simultaneously "fixes" the Y2038 problem. Other
: people will want to get reentrant timezone handling. Thankfully,
: Bernstein is not on the committee (that I've seen) so at least there's
: nobody insisting that the only possible correct approach is to import
: libtai.

Uggg. We'll at least there's that :-)

It would only take a small change too to fix this botch...

Warner

0 new messages