Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 06 Aug 2005 00:16:20 -0600 (MDT)
From:      "M. Warner Losh" <imp@bsdimp.com>
To:        standards@freebsd.org
Subject:   Inconsistancy between mktime and system time accross leapsecond
Message-ID:  <20050806.001620.82098789.imp@bsdimp.com>

next in thread | raw e-mail | index | archive | help
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;
 	}
 	/*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050806.001620.82098789.imp>