cisco / ChezScheme

Chez Scheme
Apache License 2.0
6.99k stars 987 forks source link

dates, leap seconds #534

Open ocyzl opened 4 years ago

ocyzl commented 4 years ago

http://cisco.github.io/ChezScheme/csug9.5/system.html#./system:h10 says about dates:

As for time objects, a nanosecond is an exact integer less than 109. A date-object second is, however, an exact nonnegative integer less than 62. (The values 61 and 62 allow for leap seconds.)

Nanosecond has to be nonnegative too, right?

I don't think they ever add two leap seconds in one day. (They did once add two in one year, in June and December 1972.) Also, seconds start from 0, so the last second of a minute is usually 59, and a leap second is 60, not 61.

Likewise, 62 should be 61 in the description of make-date:

sec represents seconds and must be an exact nonnegative integer less than 62.

Also in make-date, there's a missing "and" in:

mon represents the month must be an exact integer, 1 ≤ mon ≤ 12.

Here's what happens when I try to use a second of 59, 60, 61, and 62:

(make-date 0 59 59 23 31 12 2016 0) #<date Sat Dec 31 23:59:59 2016>

(make-date 0 60 59 23 31 12 2016 0) Exception in make-date: invalid day 31 for month 12 and year 2016

(make-date 0 61 59 23 31 12 2016 0) Exception in make-date: invalid day 31 for month 12 and year 2016

(make-date 0 62 59 23 31 12 2016 0) Exception in make-date: invalid second 62

59 works, as expected. 61 and 62 don't work, as expected, but give different errors for some reason. 60 doesn't work, but I think it should, because a leap second was in fact added at the end of December 2016.

ocyzl commented 4 years ago

From the same section of the Chez Scheme User's Guide:

A time-zone offset represents the time-zone offset, in seconds, from UTC. It is an exact integer in the range -86400 to +86400, inclusive. For example, Eastern Standard Time (EST), which is 5 hours east, has offset 5 × 3600 = -18000.

The last sentence should instead be:

For example, Eastern Standard Time (EST), which is 5 hours west, has offset -5 × 3600 = -18000.

ocyzl commented 4 years ago

In the description of date-year-day:

A year-day is an exact nonnegative integer less than 367, where 0 represents the first day of the year (January 1), 1 the second day, 2 the third, and so on.

I think "less than 367" should be "less than 366". If days start at 0, the last day of the year is 365 in a leap year, and 364 otherwise.

akeep commented 3 years ago

Thanks for the comments, we should improve the documentation on this.

As far as the bug, unfortunately we are relying on the functionality provided by the underlying mktime implementation from the C library, and it appears in this instance it is unaware of the leap seconds.