php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74355 DateInterval::format() with "%F" sometimes shows incorrect value by 1us
Submitted: 2017-04-01 01:35 UTC Modified: 2020-09-01 12:48 UTC
Votes:1
Avg. Score:1.0 ± 0.0
Reproduced:0 of 1 (0.0%)
From: for-bugs at hnw dot jp Assigned: cmb (profile)
Status: Closed Package: Date/time related
PHP Version: 7.1.3 OS: Any
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: for-bugs at hnw dot jp
New email:
PHP Version: OS:

 

 [2017-04-01 01:35 UTC] for-bugs at hnw dot jp
Description:
------------
From PHP 7.1.0, DateInterval::format() supports "%F" parameter which shows fraction of DateInterval. However, sometimes "%F" prints incorrect value because of floating point inaccuracy.

Test script:
---------------
<?php
$dt1=new DateTime("2000-01-01 00:00:00");
$dt2=new DateTime("2006-01-02 03:04:05.524287");
$interval = $dt1->diff($dt2);
var_dump($interval->format("%R%Y-%M-%D %H:%I:%S.%F"));


Expected result:
----------------
string(25) "+06-00-01 03:04:05.524287"

Actual result:
--------------
string(25) "+06-00-01 03:04:05.524286"

Patches

date-interval-format-fraction.patch (last revision 2017-04-01 06:27 UTC by for-bugs at hnw dot jp)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-04-01 06:31 UTC] for-bugs at hnw dot jp
Another example:

<?php
$dt1=new DateTime("2000-01-01 00:00:00");
$dt2=new DateTime("2006-01-02 03:04:05.000251");
$interval = $dt1->diff($dt2);
var_dump($interval->format("%R%Y-%M-%D %H:%I:%S.%F"));
/* Output: string(25) "+06-00-01 03:04:05.000250" */
 [2017-04-21 11:59 UTC] heiglandreas@php.net
The floating-point inaccuracy you are describing is far below the millisecond-range. The fraction-issue you are pointing out here relates to a mismatch of 299 meters when you're calculating distances based on the speed of light… 
In GPS a timing-error of 0.0001 second results in a 0.8m offset, so for the timing error we're talking about here we have an offset of 8mm 

Is this really relevant?

I'd rather say we document that it might be possible that the last digit of the fraction might be off by one.
 [2017-04-30 08:48 UTC] for-bugs at hnw dot jp
> The floating-point inaccuracy you are describing is far below the millisecond-range. The fraction-issue you are pointing out here relates to a mismatch of 299 meters when you're calculating distances based on the speed of light…
> In GPS a timing-error of 0.0001 second results in a 0.8m offset, so for the timing error we're talking about here we have an offset of 8mm 
> 
> Is this really relevant?

It is a different topic whether there is a bug or not and whether the bug is harmful or not. Of course you know.

In addition, this bug report also points out the asymmetry on the implementation of DateTime.

<?php
$dt1=new DateTime("2000-01-01 00:00:00");
$dt2=new DateTime("2006-01-02 03:04:05.000251");
$interval = $dt1->diff($dt2);
var_dump($interval->format("%R%Y-%M-%D %H:%I:%S.%F"));
/* Output: string(25) "+06-00-01 03:04:05.000250" */
$dt3 = $dt1->add($interval);
var_dump($dt3->format);
/* Output: string(26) "2006-01-02 03:04:05.000251" */

Datetime::format() can handle up to the last digit of microsecond. And its implementation is the same as the patch I wrote.

This asymmetry would cause confusion.

> I'd rather say we document that it might be possible that the last digit of the fraction might be off by one.

Of course there is no problem as long as it is documented.

However, even #74356 points out the lack of the documentation for this implementation, there is no response for a month.
 [2017-04-30 08:53 UTC] for-bugs at hnw dot jp
I'm sorry, example code is incorrect. Fixed version:

<?php
$dt1=new DateTime("2000-01-01 00:00:00");
$dt2=new DateTime("2006-01-02 03:04:05.000251");
$interval = $dt1->diff($dt2);
var_dump($interval->format("%R%Y-%M-%D %H:%I:%S.%F"));
/* Output: string(25) "+06-00-01 03:04:05.000250" */
$dt3 = $dt1->add($interval);
var_dump($dt3->format("Y-m-d H:i:s.u"));
/* Output: string(26) "2006-01-02 03:04:05.000251" */
 [2020-09-01 12:48 UTC] cmb@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: cmb
 [2020-09-01 12:48 UTC] cmb@php.net
Yes, that was a bug, and the attached patch would have helped;
however, as of PHP 7.2.0 the microseconds are no longer stored as
doubles, but rather as integers, so this issue is resolved.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Nov 23 15:01:29 2024 UTC