[sf-lug] noon, midnight, A.M., P.M., leap seconds, a bit on NTP, etc.

Michael Paoli Michael.Paoli at cal.berkeley.edu
Sun Dec 14 13:13:35 PST 2008

Or ... boundary cases matter, and ambiguity can be (quite) problematic.

Technically, noon and midnight, are neither a.m. nor p.m., but
conventions vary.[1]

In many practices - e.g. often including computers, operations, etc.,
the times will be specified using a 24 hour clock[2], with 12:00 for
noon.  For midnight[3] there's yet another ambiguity, and to avoid
that, 00:00[4] is generally used to indicate the start of the day, and
24:00[4] the end of the day.

The term "midnight" more commonly implies the time at the end of the
day, rather than the start, but is itself also somewhat ambiguous in
that regard.  In many practices, to avoid confusion, and where the time
may be selected, folks will pick a time a minute before, or after, just
to avoid potential confusion.  Of course, when one needs to refer to a
specific point in time (at least for most all civil and scientific
purposes) one needs an unambiguous means to do so.  Also including
timezone and date, in unambiguous format, is also important -
particularly where the point in time may otherwise be ambiguous.  E.g.
for GNU date(1):
$ date -Iseconds; TZ=GMT0 date -Iseconds

In many contexts, commonly, e.g. with 12 hour electronic digital
clocks, noon is considered/displayed as 12:00 p.m. and midnight 12:00
a.m.  Though that may not be precisely technically correct for that
point in time, it happens to be consistent with the entire contiguous
hour that that hour is displayed, and is correct except for the exact
point in time of precisely noon and midnight.  Note however, that some
conventions use or suggest the reverse[5] - perhaps that is in an
attempt to be more consistent with the more common notion that
midnight, at least otherwise unqualified, is more commony used to refer
to the end of the day than the start of the day (and thus if one were
to consider midnight as p.m., then it would relatively logically follow
that in such case, noon must then be a.m.).

And don't forget leap seconds![6]  How many seconds between
2008-12-31T23:59:59+0000 and 2009-01-01T00:00:00+0000 ?
Two!  At 2008-12-31T23:59:60+0000 we get a leap second this year.  So
yes, the valid range of seconds after the minute is [0-61) (in
mathematical terms - including zero, and up to but not including 61)
... or, for programming and computer science, the portion comprising
the integer number of seconds after the minute has the range from 0
through 60.  Note also that a leap second can also be *subtracted* -
though this has never occurred, and probably never will.

There have been proposals to abolish the leap second[7] (e.g. like the
boneheaded proposal submitted in September 2004 by the United States
delegation to ITU-R working party 7A), but it's unlikely the current
use of leap seconds would change anytime particularly soon.

So ... don't have your program barf if it gets 60 for the integral
number of seconds after the minute, and not all minutes are 60 seconds
long - some are 61 (and theoretically some could be 59, but that hasn't
happened thus far, and remains unlikely).  So, 2008 (also being a leap
year) is 31622401(=366*60*60*24+1) seconds long - making it one of the
longest years in a while - matching 1992 and 1976, and only being
surpassed by 1972, which was a double leap second leap year.

At quick glance on distribution readily at hand, we can see the leap
seconds for the right/PST8PDT timezone, but the PST8PDT timezone
doesn't include leap seconds.  Note that Unix system time[8] is seconds
since the (Unix) epoch - but not including leaps seconds - so some of
the details[9] get even a bit more interesting.

$ zdump -v right/PST8PDT | sed -ne 's/^[^ ]* *\(.*e.*08 PST\) i.*$/\1/p'
Wed Dec 31 23:59:60 2008 UTC = Wed Dec 31 15:59:60 2008 PST
Thu Jan  1 00:00:00 2009 UTC = Wed Dec 31 16:00:00 2008 PST

$ TZ=right/PST8PDT; export TZ
$ touch -t 200812311559.59 200812311559.59
$ touch -t 200812311559.60 200812311559.60
$ touch -t 200812311600.00 200812311600.00
$ for tmp in *; do stat -c '%n %Y %y' "$tmp"; done; unset tmp
200812311559.59 1230768022 2008-12-31 15:59:59.000000000 -0800
200812311559.60 1230768023 2008-12-31 15:59:60.000000000 -0800
200812311600.00 1230768024 2008-12-31 16:00:00.000000000 -0800
$ ls -on --full-time *
-rw------- 1 1607 0 2008-12-31 15:59:59.000000000 -0800 200812311559.59
-rw------- 1 1607 0 2008-12-31 15:59:60.000000000 -0800 200812311559.60
-rw------- 1 1607 0 2008-12-31 16:00:00.000000000 -0800 200812311600.00


1. http://en.wikipedia.org/wiki/12-hour_clock
2. http://en.wikipedia.org/wiki/24-hour_clock
3. http://en.wikipedia.org/wiki/Midnight
4. http://en.wikipedia.org/wiki/24-hour_clock#Midnight_00:00_and_24:00
5. http://www.gpoaccess.gov/stylemanual/2000/chapter_txt-12.html



Nelson, McCarthy, et al.:
The leap second: its history and possible future
Metrologia, Vol. 38, pp. 509529, 2001
(PDF in various locations on the web, HTML available via Google,
possibly other sources)

table of leap seconds:

7. http://www.cl.cam.ac.uk/~mgk25/time/leap/#abolish
8. http://en.wikipedia.org/wiki/Unix_time
9. http://www.cis.udel.edu/~mills/leap.html#reckon

daylight saving changes, UNIX/LINUX/... time, etc.

timezone files, documentation, & related

More information about the sf-lug mailing list