bug-guile
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#22034: time-utc->date shows bogus zone-dependent leap second


From: Mark H Weaver
Subject: bug#22034: time-utc->date shows bogus zone-dependent leap second
Date: Sun, 28 Oct 2018 16:39:19 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux)

Hi John,

John Cowan <address@hidden> writes:

> On Mon, Oct 22, 2018 at 2:12 AM Mark H Weaver <address@hidden> wrote:
>
>  Universal Time (UT) is not a measure of physical time, but rather is a
>  measure of the rotation angle of the Earth with respect to distant
>  quasars.  A UT second is identified with a fixed amount of rotation of
>  the Earth, which equals 1/86400 of a mean solar day.  That's why every
>  day has 86400 UT seconds.  
>
> Quite right.  Buit the whole point of UTC is that its seconds are not angles,
> but SI = TAI seconds.

I believe you're making a subtle error in your identification of UTC
seconds with TAI seconds.  It might be helpful to consider an analogy to
spatial measurement.

A TAI clock aims to measure the current TAI time, i.e. to measure the
time interval between the epoch and _you_ in units of TAI seconds,
i.e. SI seconds as observed on the geoid.

In spatial terms, a TAI clock is analogous to a very precise measuring
tape which aims to measure the distance between you and an fixed
conventional point in space, analogous to the TAI epoch.

In this analogy, a UTC clock is analogous to an equally precise
measuring tape that is _almost_ identical to the TAI analogue measuring
tape, but subtly different.  If we place the two measuring tapes side by
side and ignore pre-1972, we see that the markings are in _precisely_
the same positions along the entire length of the tape, without the
slightest deviation, even over long distances.

The difference between the two measuring tapes is that they assign
different numbers to the markings, and moreover that the UTC analogue
has a small handful of places where two adjacent markings have the same
number assigned, and all subsequent numbers are shifted by 1.  Such a
place might look something like this:

  126230388 |--
  126230389 |--
  126230390 |------------
  126230391 |--
  126230392 |--
  126230393 |--
  126230394 |--
  126230395 |------
  126230396 |--
  126230397 |--
  126230398 |--
  126230399 |--
  126230400 |------------
  126230400 |------------
  126230401 |--
  126230402 |--
  126230403 |--
  126230404 |--
  126230405 |------
  126230406 |--
  126230407 |--
  126230408 |--
  126230409 |--
  126230410 |------------
  126230411 |--
  126230412 |--

By asserting that UTC seconds are the same as TAI seconds, you're
emphasizing that the distance between any two adjacent markings are
precisely the same on the two measuring tapes.

What I'm trying to say is that when you use these two measuring tapes to
measure the interval between two arbitrary points, they will give
different answers, unless the entire interval happens to be between two
adjacent leap seconds (and post-1971).

I think it's highly questionable to claim that these two measuring tapes
measure the same units, given that when they are actually used to
measure intervals, they give different answers, and moreover that the
discrepancy grows without bound as larger intervals are measured, even
in an idealized thought experiment.

> There are a variable number of these in a day, and a UTC clock will
> indeed report 23:59:60 at the end of a day with a leap second in it

That's something that can be done when you convert TIME-TAI into a UTC
date, and indeed 'time-tai->date' from SRFI-19 will do this:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> ,pp (map (lambda (n)
                                (let* ((tai (make-time time-tai 0 n)))
                                  (list (time-second tai)
                                        (date->string (time-tai->date tai 0)
                                                      "~4"))))
                              (iota 5 126230410))
$1 = ((126230410 "1973-12-31T23:59:58Z")
      (126230411 "1973-12-31T23:59:59Z")
      (126230412 "1973-12-31T23:59:60Z")
      (126230413 "1974-01-01T00:00:00Z")
      (126230414 "1974-01-01T00:00:01Z"))
--8<---------------cut here---------------end--------------->8---


However, let's return to our disagreement which started this digression:

> On Sat, Oct 20, 2018 at 5:43 PM Mark H Weaver <address@hidden> wrote:
>
>  If I understand correctly, 'time-utc->date' should never return a date
>  object with 60 in the seconds field, because those extra seconds have no
>  representation in time-utc.  They only have representations in time-tai
>  and time-monotonic.
>
> As I understand it, this is incorrect.  UTC days can contain either
> 86400 or 86401 seconds (or in principle a different number), depending
> on whether the day has a leap second.

You seem to be asserting above that TIME-UTC _does_ have representations
of the extra leap seconds.  That is simply not true.  It's true that
*date objects* for UTC, broken down into separate fields, are able to
represent the leap seconds by putting 60 in the seconds field.  However,
TIME-UTC, represented as a single number of seconds since the epoch, is
_not_ able to represent them.

Let's look at a small interval near a leap second, in TIME-TAI,
TIME-UTC, and the corresponding date objects expressed in UTC:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> ,pp (map (lambda (n)
                                (let* ((tai (make-time time-tai 0 n))
                                       (utc (time-tai->time-utc tai)))
                                  (list (time-second tai)
                                        (time-second utc)
                                        (date->string (time-tai->date tai 0)
                                                      "~4"))))
                              (iota 5 126230410))
$2 = ((126230410 126230398 "1973-12-31T23:59:58Z")
      (126230411 126230399 "1973-12-31T23:59:59Z")
      (126230412 126230400 "1973-12-31T23:59:60Z")
      (126230413 126230400 "1974-01-01T00:00:00Z")
      (126230414 126230401 "1974-01-01T00:00:01Z"))
--8<---------------cut here---------------end--------------->8---

As you can see, 1973-12-31T23:59:60Z and 1974-01-01T00:00:00Z have the
same representation in TIME-UTC.  This is an unavoidable consequence of
the fact that TAI-UTC=12 shortly before midnight 1974-01-01 UTC, and
TAI-UTC=13 shortly after.

This is the basis for my claim that TIME-UTC is unable to represent leap
seconds, and that 'time-utc->date' should never return 60 in the seconds
field.  In theory, we could have it return 60 in the seconds field when
the input is 126230400 UTC seconds, but if we did that, then we'd be
skipping 1974-01-01T00:00:00Z.

So, what about my claim that every UTC day has 86400 UTC seconds,
although UTC days can have between 86399 and 86401 TAI seconds?  Let's
look at a similar table as above, but for the previous day:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> ,pp (map (lambda (n)
                                (let* ((tai (make-time time-tai 0 n))
                                       (utc (time-tai->time-utc tai)))
                                  (list (time-second tai)
                                        (time-second utc)
                                        (date->string (time-tai->date tai 0)
                                                      "~4"))))
                              (iota 5 (- 126230410 86400)))
$3 = ((126144010 126143998 "1973-12-30T23:59:58Z")
      (126144011 126143999 "1973-12-30T23:59:59Z")
      (126144012 126144000 "1973-12-31T00:00:00Z")
      (126144013 126144001 "1973-12-31T00:00:01Z")
      (126144014 126144002 "1973-12-31T00:00:02Z"))
--8<---------------cut here---------------end--------------->8---

The difference between the TIME-TAI values for 1973-12-31T00:00:00Z and
1974-01-01T00:00:00Z is 126230413-126144012 = 86401, but the difference
between the corresponding TIME-UTC values is 126230400-126144000 =
86400.

Does that make sense?

    Regards,
      Mark





reply via email to

[Prev in Thread] Current Thread [Next in Thread]