Re: What TZ do you use to get right time w/ clockspeed?

[email protected] (Paul Jarc) Fri, 15 Nov 2002 19:15:08 -0500
Newsgroups gmane.comp.lib.libtai
Organization What did you have in mind? A short, blunt, human pyramid?
Message-ID <[email protected]>
Bennett Todd <[email protected]> wrote:
> In fairness, I should add at this point that I've not read the POSIX
> standards at all;

From <URL:http://www.opengroup.org/>:

# The gettimeofday() function shall obtain the current time, expressed
# as seconds and microseconds since the Epoch [...]

# The time() function shall return the value of time in seconds since
# the Epoch.

At first glance, this seems to clearly require a TAI clock.  But
that's if we use common sense, which isn't POSIX-compliant.  In a
separate section:

# Seconds Since the Epoch
#
# A value that approximates the number of seconds that have elapsed
# since the Epoch. A Coordinated Universal Time name (specified in terms
# of seconds (tm_sec), minutes (tm_min), hours (tm_hour), days since
# January 1 of the year (tm_yday), and calendar year minus 1900
# (tm_year)) is related to a time represented as seconds since the
# Epoch, according to the expression below.
#
# If the year is <1970 or the value is negative, the relationship is
# undefined. If the year is >=1970 and the value is non-negative, the
# value is related to a Coordinated Universal Time name according to the
# C-language expression, where tm_sec, tm_min, tm_hour, tm_yday, and
# tm_year are all integer types:
#
# 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

So this seems to require that the clock count only non-leap seconds;
this formula calculates the total number of seconds based on the
number of days, etc., and every day is exactly 86400 seconds according
to this formula.  In reality, some days have 86401 seconds, but this
formula does not include those extra seconds in "seconds since the
Epoch".

But then the following makes it somewhat less clear, since "actual
time of day" is not defined or exemplified:

# The relationship between the actual time of day and the current value
# for seconds since the Epoch is unspecified.
#
# How any changes to the value of seconds since the Epoch are made to
# align to a desired relationship with the current actual time are made
# is implementation-defined. As represented in seconds since the Epoch,
# each and every day shall be accounted for by exactly 86400 seconds.

When in doubt, we go by implementations.  They seem to agree that
POSIX requires, or at least allows, the clock to count only non-leap
seconds.

The definition of "seconds since the Epoch" to mean "non-leap seconds
since the Epoch" means the POSIX clock is jumpy, but it makes
localtime() and gmtime() easier to implement, since every day has
exactly 86400 seconds, and every minute has exactly 60 seconds.  When
a right/ zone is in use, ADO's localtime() and gmtime() will take on
the burden of doing more complex calculations, incorporating
information about leap seconds stored in the right/ zone files, so
that we can enjoy the luxury of a non-jumpy clock.

> However, Greg Woods on the postfix list is absolutely adamant that
> all existing implementations are plughed, but that POSIX actually
> mandates the exact behavior we've been wanting --- Unix clock
> maintains a fixed relationship with TAI.

I can't see any such requirement in the above text.  He seems to be
interpreting "seconds since the Epoch" in a common-sense way;
unfortunately, POSIX defines that term with a non-common-sense
meaning, and the opengroup site doesn't link to that definition from
the parts of the spec that use the term.

He mentions that NetBSD's localtime() documentation credits Bradley
White for leap-second handling; I'm assuming this is to point out that
ADO is not credited.  But ADO's library itself credits Bradley White,
so I would guess that NetBSD's library is indeed ADO's.

In that thread on the Postfix list, Victor Duchovni claims to show
that a Cesium clock would count a different number of seconds than a
POSIX clock.  What he has really shown is that a Cesium clock would
count a different number of seconds than the NetBSD clock.  It remains
to show that NetBSD conforms to POSIX in this area.  (I say it does;
see above.)

If you want to post the URL for this message/thread/list to the
Postfix list, that might help clear things up.  Or breed more
confusion. :)  If nothing else, you can tell people where to continue
talking about this, if they like, in a place where it's on-topic.
<URL:http://news.gmane.org/thread.php?group=gmane.comp.lib.libtai>

Hm.  Greg quoted this from POSIX:

# Coordinated Universal Time (UTC) includes leap seconds.  However, in
# POSIX time (seconds since the Epoch), leap seconds are ignored (not
# applied) to provide an easy and compatible method of computing time
# differences.  Broken-down POSIX time is therefore not necessarily
# UTC, despite its appearance.

If I'm reading this right, it says that your system clock is supposed
to be smooth - and is *supposed to disagree with your wall clock*.
POSIX *wants* your human-readable time displays to be 22 seconds off;
after enough leap seconds, a POSIX clock would say it is midnight when
the sun is high in the sky.  Wow.  But I'm willing to chalk this up to
lack of clarity.  Later we finally get something concrete:

# it is important that all conforming systems interpret "536457599
# seconds since the Epoch" as 59 seconds, 59 minutes, 23 hours 31
# December 1986

So we can see that "normal" zones comply, and right/ zones don't:
$ TZ=UTC       perl -le 'print scalar gmtime 536457599'
Wed Dec 31 23:59:59 1986
$ TZ=right/UTC perl -le 'print scalar gmtime 536457599'
Wed Dec 31 23:59:46 1986

And since you need a *larger* time_t value to produce the same
human-readable time string in a right/ zone, it's clear that the
right/ zone assumes that the system clock counts *more* seconds than
the POSIX clock does.  Since leap seconds have only been added, not
removed, it must be that the right/ clock includes leap seconds, and
that the POSIX clock does not (and is therefore jumpy).

POSIX is unclear, if not downright self-contradictory.  But clearly
implementations (other than libtai and right/ zones) all agree with
each other, and disagree with Greg.  But then Greg seems to go back
and agree with everyone else:

> non-POSIX compliant localtime()/mktime() implementations which try
> to account for historical leap seconds

Sounds like right/ zones to me.  I know what code does, and I readily
take POSIX to mean what implementations think it means, but I can't
keep track of what Greg thinks.


paul