php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #70335 DateTime doesn't take into account leap seconsa
Submitted: 2015-08-23 16:15 UTC Modified: 2015-08-26 10:08 UTC
From: teo8976 at gmail dot com Assigned:
Status: Not a bug Package: Date/time related
PHP Version: 7.0.0RC1 OS:
Private report: No CVE-ID: None
 [2015-08-23 16:15 UTC] teo8976 at gmail dot com
Description:
------------
https://en.wikipedia.org/wiki/Leap_second#Insertion_of_leap_seconds

Test script:
---------------
https://3v4l.org/DL88F

<?php
$date=date_create("Jun 30 2015 23:59:59", new DateTimeZone("UTC"));
print_r($date);
print_r($date->getTimeStamp());
echo "\n";
$date= $date->add(new DateInterval("PT1S"));
print_r($date);
print_r($date->getTimeStamp());

$date2=date_create("now", new DateTimeZone("UTC"));
$date2->setTimeStamp("1435708799");
print_r($date2);
$date2->setTimeStamp("1435708801");
print_r($date2);

Expected result:
----------------
Adding one second to jun 30 2015 23:59:59 UTC should yield jun 30 2015 23:59:60 UTC because of the leap second. Same for 2012 (and a few more years).

If the timestamp 1435708799 corresponds to jun 30 2015 23:59:59, which it shouldn't because it is calculated without taking into account the 25 leap seconds occurred since the beginning of the Unix Epoch until that date, but if it was, then  1435708800 should correspond to jun 30 2015 23:59:60 and 1435708801 should be jul 1 2015 00:00:00

Actual result:
--------------
Leap seconds are not taken into account, as if they didn't exist. No 23:59:60 time exists for the days where it should, and the conversion between timestamps and UTC is therefore offset of a few seconds depending on the date, up to 26 seconds today.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-08-23 16:18 UTC] teo8976 at gmail dot com
> and the conversion between timestamps and UTC is therefore offset 
> of a few seconds


And of course adding date/time intervals may result in inaccurate times as demonstrated in the example.
 [2015-08-23 16:45 UTC] derick@php.net
-Status: Open +Status: Not a bug
 [2015-08-23 16:45 UTC] derick@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

PHP uses the proleptic Gregorian calendar 
which doesn't do leap seconds.
 [2015-08-23 16:57 UTC] teo8976 at gmail dot com
How is it not a bug calling UTC what is not UTC??
 [2015-08-23 17:02 UTC] teo8976 at gmail dot com
And how is it not a bug to arbitrarily adopt a calendar that is not the one the whole industrialized world currently agrees upon?
 [2015-08-23 23:20 UTC] teo1978 at gmail dot com
> http://derickrethans.nl/leap-seconds-and-what-to-do-with-them.html

Ok, so I was wrong about unix timestamps, since leap seconds are by definition mapped to the same unix timestamp as the previous second.

Still, I don't know from where you get that proleptic Gregorian calendar "does not do leap seconds".
Isn't ISO 8601 the standard that defines it? That standard does have leap seconds.

From the interesting link you point to, the only relevant part I get is:
"PHP uses Unix time, and does not care about leap seconds."

But I don't see any explanation of why that should be acceptable when dealing with DateTime objects, which are supposed to represent dates in accordance to internetional standards.

You are basically saying "we do it wrong because we don't give a ****".

Every other computer system exchange dates and times between them taking into account leap seconds, and PHP just doesn't? How is that supposed to be ok?

It's as if you said "PHP uses a variant of UTF-8 that doesn't have character 'ë', it's by design."
 [2015-08-26 08:08 UTC] a at b dot c dot de
ISO 8601 mandates use of the Gregorian calendar for the representation of dates and UTC for times; it does not specify what the Gregorian calendar or UTC actually are.

The Gregorian calendar is a system for generating unique identifiers for days that was introduced a few hundred years ago; "proleptic" means using it to identify dates prior to its introduction (e.g., writing "22 August 79AD" instead of "DCCCXXXII AUC IX kal. sept.").

ISO 8601's contribution is limited to specifying that the date be written as "79-08-22".

UTC is defined by the ITU and maintained by the BIPM.

Provision for leap seconds is maintained by the IERS.



Myself, I might expect that "1981-05-30T11:59:59+12:00" plus one second would be "1981-05-30T11:59:60+12:00" instead of "1981-05-31T12:00:00+12:00" - the information is there and provision is made for reading it - but if Unix timestamps are being used as the internal representation, then I can see where the information is being lost.
 [2015-08-26 10:05 UTC] a at b dot c dot de
Mind you, I've yet to find a system that _does_ return "1981-06-30T23:59:60+00:00" for the second following "1981-06-30T23:59:59+00:00". They've all been returning the same thing as PHP: "1981-07-01T00:00:00+00:00".
 [2015-08-26 10:08 UTC] teo8976 at gmail dot com
> Myself, I might expect that "1981-05-30T11:59:59+12:00" 
> plus one second would be "1981-05-30T11:59:60+12:00" 
> instead of "1981-05-31T12:00:00+12:00"

Not only you and me might expect that, that's the only acceptable outcome, given that it is how time is standardised in the whole industrialized world.
Whether we like leap seconds or not (and there are proposals around about abolishing them and adopting alternative systems) they are there.


> but if Unix timestamps are being used as the internal representation,
> then I can see where the information is being lost.

It's pretty obvious that that is where the information is lost, and I can see why it's difficult to fix, but one can't just close their eyes and say it's not a bug. 

Using unix timestamps (and nothing more) for the internal representation is the CAUSE of the bug. It's a design decision that doesn't take into account that one would loose information about leap seconds. And hence, it's a wrong design decision.

If classes like DateTime, DateInterval etc exist, and you are allowed to do operations with them plus one second, then they have to yield the correct result, full stop. 
And there is no ambiguity as to what the correct result is.

Right, you are supposed to be able to set and get unix timestamps, and you can loose information there, and you may get inconsistencies between some_date+n_seconds and some_date -> timestamp+n_seconds -> date, and those are headaches. 

Also, as far as I understand, leap seconds are not predictable in advance for many years but are "announced" every now and then. That's another headache too, because a system must be put in place in order to be able to update the information (use a file that can be replaced or something, without having to recompile PHP), etc.

What must be done (and it's astonishing that it hasn't been done for about nine years) is talk about how to solve those headaches, not just ignore them and claim there's no bug.

Otherwise, again, it is as if a function supposed to compute the length of a string returned 4 characters for "ÄË" and you told me it's correct because bytes are used for storing strings and characters Ä and Ë use 2 bytes.
That's not correct and that's why mb_string functions were invented.


Given that DateTime was introduced in 5.2 which was released in this century, it's ridiculous that it is disfunctional from the beginning.

It would be a shame if, having started in 2006 with a set of supposed-to-be-high-level classes like DateTime and DateInterval, we should end up with a separate set of classes which are actually accurate, such as sc_DateInterval (sc for "standard compliant") or RealDateInterval or the like.
We then would have to know that we should use them instead of regular DateTime classes if we care about them to be accurate, just like now we have to constantly avoid the whole set of basic string functions such as strlen, which are useless in the today world, and always use the multibyte equivalent.
 [2015-08-26 10:14 UTC] teo8976 at gmail dot com
> Mind you, I've yet to find a system that _does_ return 
> "1981-06-30T23:59:60+00:00" for the second following 
> "1981-06-30T23:59:59+00:00".

So what. I would report the bug to those systems too if I knew and used them.

Browsers also usually all have the same bugs. If they didn't fix them based on the fact that all other browsers have the same bug, they would still have all their bugs unfixed.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Jun 14 12:01:29 2024 UTC