GNU bug report logs - #26632
TAI<->UTC conversion botches 1961 to 1971

Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.

Package: guile; Reported by: Zefram <zefram@HIDDEN>; dated Mon, 24 Apr 2017 01:03:02 UTC; Maintainer for guile is bug-guile@HIDDEN.

Message received at 26632 <at> debbugs.gnu.org:


Received: (at 26632) by debbugs.gnu.org; 6 Nov 2018 04:21:51 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Mon Nov 05 23:21:51 2018
Received: from localhost ([127.0.0.1]:35905 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1gJssB-0007TC-5x
	for submit <at> debbugs.gnu.org; Mon, 05 Nov 2018 23:21:51 -0500
Received: from river.fysh.org ([87.98.248.19]:36247 ident=Debian-exim)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <zefram@HIDDEN>) id 1gJss9-0007T4-6N
 for 26632 <at> debbugs.gnu.org; Mon, 05 Nov 2018 23:21:49 -0500
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=fysh.org;
 s=20170316; h=In-Reply-To:Content-Type:MIME-Version:References:Message-ID:
 Subject:Cc:To:From:Date:Sender:Reply-To:Content-Transfer-Encoding:Content-ID:
 Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
 :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:
 List-Post:List-Owner:List-Archive;
 bh=TPTkGLq96CT9m6CXLf2GUACkVLIV+1vaSVr1BfulrLc=; b=WJ6dnYuheKYYcC0cB5PjqbzCI5
 M3uYvBRNK+AGWrBIWktFmknnCqQpHX/fQ3L2q5Iq0WM9SHcXEnduUli6bz39XkMWRuBkxpfAKxWqH
 4s2O2k26w7GVTRW2OL5j5ZUG2PS/GdFztaqiA80iJx13JxRkyTtYN3aoElqt1hR0mT8M=;
Received: from zefram by river.fysh.org with local (Exim 4.89 #1 (Debian))
 id 1gJss4-00040y-3X; Tue, 06 Nov 2018 04:21:44 +0000
Date: Tue, 6 Nov 2018 04:21:44 +0000
From: Zefram <zefram@HIDDEN>
To: Mark H Weaver <mhw@HIDDEN>
Subject: Re: bug#26632: TAI<->UTC conversion botches 1961 to 1971
Message-ID: <20181106042144.rglcwbfdfmwo7dyc@HIDDEN>
References: <20170424010218.GL6765@HIDDEN>
 <87zhv3yjhu.fsf@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <87zhv3yjhu.fsf@HIDDEN>
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: 26632
Cc: 26632 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Mark H Weaver wrote:
>patch adds the TAI-UTC tables for 1961-1971 and uses them to implement
>TAI<->UTC conversions over that time range with nanosecond accuracy.

On a quick inspection of the code, that looks good.

>        I'm vaguely concerned about violating widely-held assumptions,
>e.g. that UTC runs at the same rate as TAI

If an application assumes that for pre-1972 times, then the application
is broken.  Note that any application currently using the srfi-19 library
for pre-1972 TAI<->UTC conversions already has a bigger problem, in that
it's getting false answers from the library.  It's hard to see how fixing
the library could make any previously-working program stop working.

>             which might cause some code on top of Guile to misbehave if
>the system clock is set pre-1972,

If the system clock is incorrect by decades, there will be many other
problems to deal with.

>I'm curious to hear opinions on this.

My view is that this change should definitely be applied.  But it's also
worth thinking about what the alternative is, if the correct conversions
are somehow too shocking for innocent programs to be exposed to them.
Making no change isn't a realistic option: the library is producing
false answers, which are no use to anyone.  It's clearly a bug in the
library, and needs to be addressed somehow.  The only other defensible
option would be to declare pre-1972 UTC out of scope for the library,
having attempted conversions signal an error.  That would have to be
documented, and it seems like it would still amount to a deviation from
the requirements of SRFI-19.

-zefram




Information forwarded to bug-guile@HIDDEN:
bug#26632; Package guile. Full text available.

Message received at 26632 <at> debbugs.gnu.org:


Received: (at 26632) by debbugs.gnu.org; 24 Oct 2018 18:12:03 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Wed Oct 24 14:12:03 2018
Received: from localhost ([127.0.0.1]:40467 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1gFNdT-0008Vu-5W
	for submit <at> debbugs.gnu.org; Wed, 24 Oct 2018 14:12:03 -0400
Received: from mail-wm1-f50.google.com ([209.85.128.50]:54004)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <cowan@HIDDEN>) id 1gFNdP-0008VO-Ua
 for 26632 <at> debbugs.gnu.org; Wed, 24 Oct 2018 14:12:00 -0400
Received: by mail-wm1-f50.google.com with SMTP id f8-v6so3973207wmc.3
 for <26632 <at> debbugs.gnu.org>; Wed, 24 Oct 2018 11:11:59 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=ccil-org.20150623.gappssmtp.com; s=20150623;
 h=mime-version:references:in-reply-to:from:date:message-id:subject:to
 :cc; bh=PyMhxhDEfXRqbrlkC4cbqmWyjwmyOAuzi+fsSe1CXmA=;
 b=c1gRfa65Ks53Yg/oxgESFU2H2cCDZF2x60kAy5GSas2pEZ0pLadZcXQbh6vAqZYBl7
 IKegVfrpFtYl8vY+Y9WIA4uxVmpnXtNjcyd1lo0DNtezPo6codYZcsSp60UnrSeYMR51
 chgXwIEIpPLdygPXtUp4p3G1QwcCUncJInZmXVE5PHDzxZsMVWLbSLwuDIZ/1+uUtSCJ
 TSRyue7etjq2U1nhA2s40+n2GDkEU/SFRY8JSPyF1SLFtgY3HtXU9dBjuD6Z3H8O/eoK
 bqGeo+7rR3gOL6XoSsaPkZmEf1oDsr903AL2IuB2H0ymNGsfoGlrY5DdeuDRgpZ+fNBY
 TfQA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20161025;
 h=x-gm-message-state:mime-version:references:in-reply-to:from:date
 :message-id:subject:to:cc;
 bh=PyMhxhDEfXRqbrlkC4cbqmWyjwmyOAuzi+fsSe1CXmA=;
 b=fBvL4hahY9n3TWvkUfc/v+xuxyzhGrrhlTUw85lEOGlL3EIMFhltRSf7TmPYqbwtOh
 Og/M/sQNN49tL+nFv9R2q+Bd0jSFbvI9Tdb6//50UmCU2Ct53LY1DahAbR/2f4a+mcrB
 jHRffm6+zDj7iIl7UR4L2txnRw0WLCjX9Ao0eVph5Iv9KgutpJvtPSo4SyrNvHTGUB5f
 9T3EnqOa2zrQG2qNovdw0bfMpGCaYf7jyIJLcnrpFZnio6U5/uexJAfFhFqaDjp3BFAS
 zzG3HozLFevxFtwM478/Nkk2h3vtGhaGf2LNgKULAZJqu2DmNzmb76rwgx0kLUcmytr7
 JghA==
X-Gm-Message-State: AGRZ1gIS0cMUp7HM8ovj2t2En6Nn0GS51VqTXuP2GseC48aShaMdmKI8
 DvhVruXGIhJFfa3kvEqo4urFdvTiCVqfinUhLL2ycg==
X-Google-Smtp-Source: AJdET5cjzufuSBpDj752XRzvpC4pvF1GS1h8XLQdJ4rupFI/ByFzqhbxA91uP6wAHpeX0XZwOI0Ip8IJhpZXdUXQcyQ=
X-Received: by 2002:a1c:3702:: with SMTP id e2-v6mr3534645wma.89.1540404713983; 
 Wed, 24 Oct 2018 11:11:53 -0700 (PDT)
MIME-Version: 1.0
References: <20170424010218.GL6765@HIDDEN> <87zhv3yjhu.fsf@HIDDEN>
In-Reply-To: <87zhv3yjhu.fsf@HIDDEN>
From: John Cowan <cowan@HIDDEN>
Date: Wed, 24 Oct 2018 14:11:42 -0400
Message-ID: <CAD2gp_Teq_Mp4LZQy+6YAvJYq+9=cz3y94VNCtyymMq69e8abg@HIDDEN>
Subject: Re: bug#26632: TAI<->UTC conversion botches 1961 to 1971
To: Mark H Weaver <mhw@HIDDEN>
Content-Type: multipart/alternative; boundary="000000000000c9cb770578fd6b6f"
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: 26632
Cc: zefram@HIDDEN, 26632 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--000000000000c9cb770578fd6b6f
Content-Type: text/plain; charset="UTF-8"

On Wed, Oct 24, 2018 at 1:58 AM Mark H Weaver <mhw@HIDDEN> wrote:

> This has to be examined somewhat indirectly, because SRFI-19 doesn't offer
> > any way to display a TAI time in its conventional form as a date-like
> > structure, nor to input a TAI time from such a structure.
>

I think that is as it should be.  TAI time is a count of SI seconds from a
particular instant in time.  It is not divided up into minutes, hours,
days, months, years, etc. I realize that this is often done, but I believe
it to be not actually meaningful.  These terms apply to dynamical time and
also in a slightly different way to UTC, but they have little meaning for
TAI.

-- 
John Cowan          http://vrici.lojban.org/~cowan        cowan@HIDDEN
    "Mr. Lane, if you ever wish anything that I can do, all you will have
        to do will be to send me a telegram asking and it will be done."
    "Mr. Hearst, if you ever get a telegram from me asking you to do
        anything, you can put the telegram down as a forgery."

--000000000000c9cb770578fd6b6f
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr"><br><br><div class=3D"gmail_quote"><div d=
ir=3D"ltr">On Wed, Oct 24, 2018 at 1:58 AM Mark H Weaver &lt;<a href=3D"mai=
lto:mhw@HIDDEN">mhw@HIDDEN</a>&gt; wrote:<br></div><div dir=3D"ltr"=
><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.=
8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">&gt; This has =
to be examined somewhat indirectly, because SRFI-19 doesn&#39;t offer<br>
&gt; any way to display a TAI time in its conventional form as a date-like<=
br>
&gt; structure, nor to input a TAI time from such a structure.<br></blockqu=
ote><div><br></div><div>I think that is as it should be.=C2=A0 TAI time is =
a count of SI seconds from a particular instant in time.=C2=A0 It is not di=
vided up into minutes, hours, days, months, years, etc. I realize that this=
 is often done, but I believe it to be not actually meaningful.=C2=A0 These=
 terms apply to dynamical time and also in a slightly different way to UTC,=
 but they have little meaning for TAI.</div><div><br></div><div>--=C2=A0</d=
iv><div><div>John Cowan=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <a href=3D"http:/=
/vrici.lojban.org/~cowan">http://vrici.lojban.org/~cowan</a>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 <a href=3D"mailto:cowan@HIDDEN">cowan@HIDDEN</a></div><di=
v>=C2=A0 =C2=A0 &quot;Mr. Lane, if you ever wish anything that I can do, al=
l you will have</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 to do will be to send=
 me a telegram asking and it will be done.&quot;</div><div>=C2=A0 =C2=A0 &q=
uot;Mr. Hearst, if you ever get a telegram from me asking you to do</div><d=
iv>=C2=A0 =C2=A0 =C2=A0 =C2=A0 anything, you can put the telegram down as a=
 forgery.&quot;<br><br></div></div></div></div></div>

--000000000000c9cb770578fd6b6f--




Information forwarded to bug-guile@HIDDEN:
bug#26632; Package guile. Full text available.

Message received at 26632 <at> debbugs.gnu.org:


Received: (at 26632) by debbugs.gnu.org; 24 Oct 2018 05:57:58 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Wed Oct 24 01:57:58 2018
Received: from localhost ([127.0.0.1]:39029 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1gFCB4-0005DY-5q
	for submit <at> debbugs.gnu.org; Wed, 24 Oct 2018 01:57:58 -0400
Received: from world.peace.net ([64.112.178.59]:60528)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <mhw@HIDDEN>) id 1gFCAz-0005DI-RM
 for 26632 <at> debbugs.gnu.org; Wed, 24 Oct 2018 01:57:55 -0400
Received: from mhw by world.peace.net with esmtpsa
 (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89)
 (envelope-from <mhw@HIDDEN>)
 id 1gFCAs-0004yF-Dx; Wed, 24 Oct 2018 01:57:47 -0400
From: Mark H Weaver <mhw@HIDDEN>
To: Zefram <zefram@HIDDEN>
Subject: Re: bug#26632: TAI<->UTC conversion botches 1961 to 1971
References: <20170424010218.GL6765@HIDDEN>
Date: Wed, 24 Oct 2018 01:57:33 -0400
In-Reply-To: <20170424010218.GL6765@HIDDEN> (Zefram's message of "Mon, 24
 Apr 2017 02:02:18 +0100")
Message-ID: <87zhv3yjhu.fsf@HIDDEN>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Spam-Score: 0.0 (/)
X-Debbugs-Envelope-To: 26632
Cc: 26632 <at> debbugs.gnu.org
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

--=-=-=
Content-Type: text/plain

Hi Zefram,

Zefram <zefram@HIDDEN> writes:
> The SRFI-19 library gets TAI<->UTC conversions badly wrong in the years
> 1961 to 1971 (inclusive).

Indeed.

> This has to be examined somewhat indirectly, because SRFI-19 doesn't offer
> any way to display a TAI time in its conventional form as a date-like
> structure, nor to input a TAI time from such a structure.

FWIW, here are two procedures I hacked up to support TAI dates:

--8<---------------cut here---------------start------------->8---
(define (time-tai->date-tai t . tz-offset)
  (apply time-tai->date
         (time-utc->time-tai! (make-time time-utc
                                         (time-nanosecond t)
                                         (time-second t)))
         tz-offset))

(define (date-tai->time-tai d)
  (let ((t (time-tai->time-utc (date->time-tai d))))
    (set-time-type! t time-tai)
    t))
--8<---------------cut here---------------end--------------->8---

> SRFI-19's date structure, as implemented, is always interpreted
> according to UTC.

Indeed, I discovered this as well, and found it surprising.  The text of
SRFI-19 fails to mention it, but the reference implementation makes it
quite clear.

> First I'll consider an ordinary day in 1967:
>
> scheme@(guile-user)> (use-modules (srfi srfi-19))
> scheme@(guile-user)> (time-difference
> ... (time-utc->time-tai (date->time-utc (make-date 0 0 0 0 15 3 1967 0)))
> ... (time-utc->time-tai (date->time-utc (make-date 0 0 0 0 14 3 1967 0))))
> $1 = #<time type: time-duration nanosecond: 0 second: 86400>
>
> This takes the start and end of 1967-03-14, as judged by UTC, converts
> both of these times to TAI, and asks for the duration of that TAI
> interval.  It's asking how many TAI seconds long that UTC day was.
> As described in <http://maia.usno.navy.mil/ser7/tai-utc.dat>, there
> was no UTC leap on that day, but throughout 1967 UTC had a frequency
> offset from TAI such that each UTC second lasted exactly 1.00000003 TAI
> seconds.  The correct answer to the above question is therefore exactly
> 86400.002592 s.  The answer shown above, of 86400.000000 s, is incorrect.
>
> If time-tai->time-utc is applied to the times in the above example,
> it accurately inverts what time-utc->time-tai did.  It is good that the
> conversions are mutually consistent, but in this case it means they are
> both wrong.
>
> Second, I'll consider a less ordinary day:
>
> scheme@(guile-user)> (time-difference
> ... (time-utc->time-tai (date->time-utc (make-date 0 0 0 12 1 2 1968 0)))
> ... (time-utc->time-tai (date->time-utc (make-date 0 0 0 12 31 1 1968 0))))
> $2 = #<time type: time-duration nanosecond: 0 second: 86400>
>
> This time the period considered is from noon 1968-01-31 to noon
> 1968-02-01.  The same frequency offset described above applies throughout
> this period.  The additional complication here is that at the end of
> 1968-01-31 there was a leap of -0.1 (TAI) seconds.  The true duration of
> this day is therefore exactly 86399.902592 s.  The answer shown above,
> of 86400.000000 s, is incorrect in two ways, accounting for neither the
> frequency offset nor the leap.

I've attached two patches to fix this bug.  The first lays the
groundwork by adding support for non-integer TAI-UTC deltas.  The second
patch adds the TAI-UTC tables for 1961-1971 and uses them to implement
TAI<->UTC conversions over that time range with nanosecond accuracy.

Although the code is now written, I'm unsure whether we should add it to
Guile.  I'm vaguely concerned about violating widely-held assumptions,
e.g. that UTC runs at the same rate as TAI (except when leap seconds are
introduced), which might cause some code on top of Guile to misbehave if
the system clock is set pre-1972, although admittedly such a scenario
seems unlikely.

I'm curious to hear opinions on this.

Anyway, here are the patches.

      Mark



--=-=-=
Content-Type: text/x-patch
Content-Disposition: inline;
 filename=0001-SRFI-19-TAI-UTC-conversions-support-non-integer-delt.patch
Content-Description: [PATCH 1/2] SRFI-19: TAI<->UTC conversions support
 non-integer deltas

From 3a67fbfd441b39630ff3c3201d2a731b51b1a8ee Mon Sep 17 00:00:00 2001
From: Mark H Weaver <mhw@HIDDEN>
Date: Tue, 23 Oct 2018 00:39:30 -0400
Subject: [PATCH 1/2] SRFI-19: TAI<->UTC conversions support non-integer
 deltas.

Previously, 'utc->tai' and 'tai->utc' were unary procedures and returned
a second value, mapping seconds to seconds, based on the assumption that
the nanoseconds field would never be changed by these maps.  To support
non-integer values of TAI-UTC, here we change 'utc->tai' and 'tai->utc'
to accept two arguments and return two values: nanoseconds and seconds.

* module/srfi/srfi-19 (utc->tai, tai->utc): Add an additional 'ns'
argument, and return it as an additional value.
(current-time-tai, priv:time-tai->time-utc!, priv:time-utc->time-tai!)
(time-tai->julian-day, time-monotonic->julian-day): Adapt accordingly.
---
 module/srfi/srfi-19.scm | 56 +++++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 25 deletions(-)

diff --git a/module/srfi/srfi-19.scm b/module/srfi/srfi-19.scm
index 46de91a7e..f653b1bc3 100644
--- a/module/srfi/srfi-19.scm
+++ b/module/srfi/srfi-19.scm
@@ -237,21 +237,21 @@
   (set! leap-second-table (read-tai-utc-data filename)))
 
 
-(define (utc->tai utc-seconds)
+(define (utc->tai ns utc-seconds)
   (let loop ((table leap-second-table))
     (cond ((null? table)
-           utc-seconds)
+           (values ns utc-seconds))
           ((>= utc-seconds (caar table))
-           (+ utc-seconds (cdar table)))
+           (values ns (+ utc-seconds (cdar table))))
           (else
            (loop (cdr table))))))
 
-(define (tai->utc tai-seconds)
+(define (tai->utc ns tai-seconds)
   (let loop ((table leap-second-table))
     (cond ((null? table)
-           tai-seconds)
+           (values ns tai-seconds))
           ((>= tai-seconds (+ (caar table) (cdar table)))
-           (- tai-seconds (cdar table)))
+           (values ns (- tai-seconds (cdar table))))
           (else
            (loop (cdr table))))))
 
@@ -309,9 +309,8 @@
   (let* ((tod (gettimeofday))
          (sec (car tod))
          (usec (cdr tod)))
-    (make-time time-tai
-               (* usec 1000)
-               (utc->tai sec))))
+    (receive (ns s) (utc->tai (* usec 1000) sec)
+      (make-time time-tai ns s))))
 
 ;;(define (current-time-ms-time time-type proc)
 ;;  (let ((current-ms (proc)))
@@ -460,10 +459,12 @@
 (define (priv:time-tai->time-utc! time-in time-out caller)
   (if (not (eq? (time-type time-in) time-tai))
       (time-error caller 'incompatible-time-types time-in))
-  (set-time-type! time-out time-utc)
-  (set-time-nanosecond! time-out (time-nanosecond time-in))
-  (set-time-second!     time-out (tai->utc (time-second time-in)))
-  time-out)
+  (receive (ns s) (tai->utc (time-nanosecond time-in)
+                            (time-second time-in))
+    (set-time-type! time-out time-utc)
+    (set-time-nanosecond! time-out ns)
+    (set-time-second!     time-out s)
+    time-out))
 
 (define (time-tai->time-utc time-in)
   (priv:time-tai->time-utc! time-in (make-time-unnormalized #f #f #f) 'time-tai->time-utc))
@@ -475,10 +476,13 @@
 (define (priv:time-utc->time-tai! time-in time-out caller)
   (if (not (eq? (time-type time-in) time-utc))
       (time-error caller 'incompatible-time-types time-in))
-  (set-time-type! time-out time-tai)
-  (set-time-nanosecond! time-out (time-nanosecond time-in))
-  (set-time-second!     time-out (utc->tai (time-second time-in)))
-  time-out)
+  (receive (ns s)
+      (utc->tai (time-nanosecond time-in)
+                (time-second time-in))
+    (set-time-type! time-out time-tai)
+    (set-time-nanosecond! time-out ns)
+    (set-time-second!     time-out s)
+    time-out))
 
 (define (time-utc->time-tai time-in)
   (priv:time-utc->time-tai! time-in (make-time-unnormalized #f #f #f) 'time-utc->time-tai))
@@ -807,10 +811,11 @@
 (define (time-tai->julian-day time)
   (if (not (eq? (time-type time) time-tai))
       (time-error 'time-tai->julian-day 'incompatible-time-types  time))
-  (+ (/ (+ (tai->utc (time-second time))
-           (/ (time-nanosecond time) nano))
-        sid)
-     tai-epoch-in-jd))
+  (receive (ns s) (tai->utc (time-nanosecond time)
+                            (time-second time))
+    (+ (/ (+ s (/ ns nano))
+          sid)
+       tai-epoch-in-jd)))
 
 (define (time-tai->modified-julian-day time)
   (- (time-tai->julian-day time)
@@ -820,10 +825,11 @@
 (define (time-monotonic->julian-day time)
   (if (not (eq? (time-type time) time-monotonic))
       (time-error 'time-monotonic->julian-day 'incompatible-time-types  time))
-  (+ (/ (+ (tai->utc (time-second time))
-           (/ (time-nanosecond time) nano))
-        sid)
-     tai-epoch-in-jd))
+  (receive (ns s) (tai->utc (time-nanosecond time)
+                            (time-second time))
+    (+ (/ (+ s (/ ns nano))
+          sid)
+       tai-epoch-in-jd)))
 
 (define (time-monotonic->modified-julian-day time)
   (- (time-monotonic->julian-day time)
-- 
2.19.1


--=-=-=
Content-Type: text/x-patch
Content-Disposition: inline;
 filename=0002-SRFI-19-Implement-correct-TAI-UTC-conversions-for-19.patch
Content-Description: [PATCH 2/2] SRFI-19: Implement correct TAI<->UTC
 conversions for 1961-1971

From adfcb5ee624d457a8dae33e8e122cbff6d4a1428 Mon Sep 17 00:00:00 2001
From: Mark H Weaver <mhw@HIDDEN>
Date: Tue, 23 Oct 2018 00:42:12 -0400
Subject: [PATCH 2/2] SRFI-19: Implement correct TAI<->UTC conversions for
 1961-1971.

* module/srfi/srfi-19.scm (tai-utc-1961-1971-table): New variable.
(pre-1972-utc->tai, pre-1972-tai->utc): New procedures.
(utc->tai, tai->utc): Use the new procedures.
---
 module/srfi/srfi-19.scm | 58 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 56 insertions(+), 2 deletions(-)

diff --git a/module/srfi/srfi-19.scm b/module/srfi/srfi-19.scm
index f653b1bc3..d4afa1931 100644
--- a/module/srfi/srfi-19.scm
+++ b/module/srfi/srfi-19.scm
@@ -240,7 +240,7 @@
 (define (utc->tai ns utc-seconds)
   (let loop ((table leap-second-table))
     (cond ((null? table)
-           (values ns utc-seconds))
+           (pre-1972-utc->tai ns utc-seconds))
           ((>= utc-seconds (caar table))
            (values ns (+ utc-seconds (cdar table))))
           (else
@@ -249,13 +249,67 @@
 (define (tai->utc ns tai-seconds)
   (let loop ((table leap-second-table))
     (cond ((null? table)
-           (values ns tai-seconds))
+           (pre-1972-tai->utc ns tai-seconds))
           ((>= tai-seconds (+ (caar table) (cdar table)))
            (values ns (- tai-seconds (cdar table))))
           (else
            (loop (cdr table))))))
 
 
+(define tai-utc-1961-1971-table
+  ;;      UTC start       delta@start  slope
+  ;;        (ns)             (ns)      (ns/s)
+  '(( -60480000000000000  6185682000    30)
+    (-126230400000000000  4313170000    30)
+    (-136771200000000000  4155058000    15)
+    (-142128000000000000  3974706000    15)
+    (-152668800000000000  3716594000    15)
+    (-157766400000000000  3540130000    15)
+    (-168307200000000000  3282018000    15)
+    (-181526400000000000  2983730000    15)
+    (-189388800000000000  2765794000    15)
+    (-194659200000000000  2697278800    13)
+    (-252460800000000000  1845858000    13)
+    (-265680000000000000  1647570000    15)
+    (-283996800000000000  1422818000    15)))
+
+(define (pre-1972-utc->tai ns utc-seconds)
+  (let ((utc-ns (+ ns (* nano utc-seconds))))
+    (let loop ((table tai-utc-1961-1971-table))
+      (cond ((null? table)
+             (values ns utc-seconds))
+            ((>= utc-ns (caar table))
+             (apply (lambda (utc-start delta@start slope)
+                      (let ((tai-ns (+ utc-ns
+                                       delta@start
+                                       (round-quotient (* slope (- utc-ns
+                                                                   utc-start))
+                                                       nano))))
+                        (values (truncate-remainder tai-ns nano)
+                                (truncate-quotient tai-ns nano))))
+                    (car table)))
+            (else
+             (loop (cdr table)))))))
+
+(define (pre-1972-tai->utc ns tai-seconds)
+  (let ((tai-ns (+ ns (* nano tai-seconds))))
+    (let loop ((table tai-utc-1961-1971-table))
+      (cond ((null? table)
+             (values ns tai-seconds))
+            ((>= tai-ns (+ (caar table) (cadar table)))
+             (apply (lambda (utc-start delta@start slope)
+                      (let ((utc-ns (+ utc-start
+                                       (round-quotient (* nano (- tai-ns
+                                                                  utc-start
+                                                                  delta@start))
+                                                       (+ nano slope)))))
+                        (values (truncate-remainder utc-ns nano)
+                                (truncate-quotient utc-ns nano))))
+                    (car table)))
+            (else
+             (loop (cdr table)))))))
+
+
 ;;; the TIME structure; creates the accessors, too.
 
 (define-record-type time
-- 
2.19.1


--=-=-=--




Information forwarded to bug-guile@HIDDEN:
bug#26632; Package guile. Full text available.

Message received at submit <at> debbugs.gnu.org:


Received: (at submit) by debbugs.gnu.org; 24 Apr 2017 01:02:57 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sun Apr 23 21:02:57 2017
Received: from localhost ([127.0.0.1]:36958 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1d2SOy-0006Ms-UD
	for submit <at> debbugs.gnu.org; Sun, 23 Apr 2017 21:02:57 -0400
Received: from eggs.gnu.org ([208.118.235.92]:58148)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <zefram@HIDDEN>) id 1d2SOt-0006ML-7p
 for submit <at> debbugs.gnu.org; Sun, 23 Apr 2017 21:02:52 -0400
Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)
 (envelope-from <zefram@HIDDEN>) id 1d2SOj-0008G2-MV
 for submit <at> debbugs.gnu.org; Sun, 23 Apr 2017 21:02:42 -0400
X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org
X-Spam-Level: 
X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,T_DKIM_INVALID
 autolearn=disabled version=3.3.2
Received: from lists.gnu.org ([2001:4830:134:3::11]:44954)
 by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)
 (Exim 4.71) (envelope-from <zefram@HIDDEN>) id 1d2SOj-0008Fy-Jq
 for submit <at> debbugs.gnu.org; Sun, 23 Apr 2017 21:02:37 -0400
Received: from eggs.gnu.org ([2001:4830:134:3::10]:49108)
 by lists.gnu.org with esmtp (Exim 4.71)
 (envelope-from <zefram@HIDDEN>) id 1d2SOe-00055H-RC
 for bug-guile@HIDDEN; Sun, 23 Apr 2017 21:02:37 -0400
Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)
 (envelope-from <zefram@HIDDEN>) id 1d2SOa-0008EF-DA
 for bug-guile@HIDDEN; Sun, 23 Apr 2017 21:02:32 -0400
Received: from river6.fysh.org ([2001:41d0:d:20da::2]:34710
 helo=river.fysh.org)
 by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16)
 (Exim 4.71) (envelope-from <zefram@HIDDEN>) id 1d2SOa-0008D7-39
 for bug-guile@HIDDEN; Sun, 23 Apr 2017 21:02:28 -0400
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=fysh.org;
 s=20170316; 
 h=Content-Type:MIME-Version:Message-ID:Subject:To:From:Date;
 bh=4CURIA3HFcx9WEuF2Q1PJofcTClP5tZfecA7g2TwMnI=; 
 b=XeW7voiWcVv7giQtDxh38gnYK1Ay9yqTKENDv+0zO/IX1bY2f5h10DOFP2CKSKJiXDJwl51BflIW8iiY9EwqpYhq0gYat3KbGm0AH0iDbvuMFC1OyXlig848vK6zIZBw2VG6RimMMAWakLfoxgcsHJDL7WaDroNVx3YIaOVVVMs=;
Received: from zefram by river.fysh.org with local (Exim 4.84_2 #1 (Debian))
 id 1d2SOQ-0006e3-K2; Mon, 24 Apr 2017 02:02:18 +0100
Date: Mon, 24 Apr 2017 02:02:18 +0100
From: Zefram <zefram@HIDDEN>
To: bug-guile@HIDDEN
Subject: TAI<->UTC conversion botches 1961 to 1971
Message-ID: <20170424010218.GL6765@HIDDEN>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
X-detected-operating-system: by eggs.gnu.org: Genre and OS details not
 recognized.
X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x
X-Received-From: 2001:4830:134:3::11
X-Spam-Score: -4.0 (----)
X-Debbugs-Envelope-To: submit
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -4.0 (----)

The SRFI-19 library gets TAI<->UTC conversions badly wrong in the years
1961 to 1971 (inclusive).

This has to be examined somewhat indirectly, because SRFI-19 doesn't offer
any way to display a TAI time in its conventional form as a date-like
structure, nor to input a TAI time from such a structure.  SRFI-19's
date structure, as implemented, is always interpreted according to UTC.
The only operations supported on TAI time structures are conversions to
and from the various forms of UTC, conversions to and from the less-useful
`monotonic' time, and arithmetic operations.  Thus the erroneous TAI<->UTC
conversions only come out through arithmetic operations in TAI space.
One must also be careful to avoid unrelated bugs such as bug#21911.

First I'll consider an ordinary day in 1967:

scheme@(guile-user)> (use-modules (srfi srfi-19))
scheme@(guile-user)> (time-difference
... (time-utc->time-tai (date->time-utc (make-date 0 0 0 0 15 3 1967 0)))
... (time-utc->time-tai (date->time-utc (make-date 0 0 0 0 14 3 1967 0))))
$1 = #<time type: time-duration nanosecond: 0 second: 86400>

This takes the start and end of 1967-03-14, as judged by UTC, converts
both of these times to TAI, and asks for the duration of that TAI
interval.  It's asking how many TAI seconds long that UTC day was.
As described in <http://maia.usno.navy.mil/ser7/tai-utc.dat>, there
was no UTC leap on that day, but throughout 1967 UTC had a frequency
offset from TAI such that each UTC second lasted exactly 1.00000003 TAI
seconds.  The correct answer to the above question is therefore exactly
86400.002592 s.  The answer shown above, of 86400.000000 s, is incorrect.

If time-tai->time-utc is applied to the times in the above example,
it accurately inverts what time-utc->time-tai did.  It is good that the
conversions are mutually consistent, but in this case it means they are
both wrong.

Second, I'll consider a less ordinary day:

scheme@(guile-user)> (time-difference
... (time-utc->time-tai (date->time-utc (make-date 0 0 0 12 1 2 1968 0)))
... (time-utc->time-tai (date->time-utc (make-date 0 0 0 12 31 1 1968 0))))
$2 = #<time type: time-duration nanosecond: 0 second: 86400>

This time the period considered is from noon 1968-01-31 to noon
1968-02-01.  The same frequency offset described above applies throughout
this period.  The additional complication here is that at the end of
1968-01-31 there was a leap of -0.1 (TAI) seconds.  The true duration of
this day is therefore exactly 86399.902592 s.  The answer shown above,
of 86400.000000 s, is incorrect in two ways, accounting for neither the
frequency offset nor the leap.

Once again, time-tai->time-utc accurately inverts the incorrect
time-utc->time-tai.  The failure to handle UTC's leaps in this era is
not specific to the relatively unusual negative leaps: it's equally
clueless about the positive leaps.

The full extent of the conversion errors, integrated across the entire
"rubber seconds" era from 1961-01-01 to 1972-01-01, is a little over
8.5 seconds of TAI.

This bug influences bug#26164, regarding time arithmetic in UTC.  If one
were to ignore the rubber seconds era, an obvious way to correct UTC
time arithmetic would be to convert to TAI and the arithmetic there.
That handles UTC leaps correctly.  But with rubber seconds it would
still be wrong.  In the rubber seconds era the number of UTC seconds in
an interval differs from the number of TAI seconds.

-zefram




Acknowledgement sent to Zefram <zefram@HIDDEN>:
New bug report received and forwarded. Copy sent to bug-guile@HIDDEN. Full text available.
Report forwarded to bug-guile@HIDDEN:
bug#26632; Package guile. Full text available.
Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.
Last modified: Mon, 25 Nov 2019 12:00:02 UTC

GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997 nCipher Corporation Ltd, 1994-97 Ian Jackson.