php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79420 Time off by a microsecond
Submitted: 2020-03-27 17:13 UTC Modified: 2020-03-27 17:35 UTC
From: danack@php.net Assigned:
Status: Not a bug Package: Date/time related
PHP Version: 7.4.4 OS: MacOS High Sierra 10.13.6
Private report: No CVE-ID: None
 [2020-03-27 17:13 UTC] danack@php.net
Description:
------------
Somehow, creating two DateTime objects from the same date input string, and then setting all of the time values to be 0 manages to create one of them with the wrong microseconds.

I have a testsuite that includes a test for creating a datetime object from user input and comparing them against a DateTime object created from set parameters. This test has worked for months, but just now failed twice in a row, and the DateTimes were different.

-2002-10-02T00:00:00.000001+0000
+2002-10-02T00:00:00.000000+0000

The code below is _not_ a reproduce case, but shows what PHPUnit was doing to compare the DateTimes. 

Not expecting this to be fixed as high chance it was something specific to my system, more just creating the report for posterity

Test script:
---------------
<?php

declare(strict_types = 1);


$max = 1000000;
$formatString = \DateTimeInterface::RFC3339_EXTENDED;
$absDelta = 0.0;

for ($i = 0; $i < $max; $i += 1) {
    $actual = \DateTimeImmutable::createFromFormat('Y-m-d', '2002-10-02');
    if ($actual instanceof \DateTimeImmutable) {
        $actual = $actual->setTime(0, 0, 0, 0);
    }
    usleep(rand(0, 1000));

    $expected = \DateTime::createFromFormat('Y-m-d', '2002-10-02')->setTime(0, 0, 0, 0);
    $delta    = new \DateInterval(\sprintf('PT%dS', $absDelta));
    $actualClone = (clone $actual)
        ->setTimezone(new \DateTimeZone('UTC'));

    usleep(rand(0, 1000));

    $expectedLower = (clone $expected)
        ->setTimezone(new \DateTimeZone('UTC'))
        ->sub($delta);

    usleep(rand(0, 1000));

    $expectedUpper = (clone $expected)
        ->setTimezone(new \DateTimeZone('UTC'))
        ->add($delta);

    if ($actualClone < $expectedLower || $actualClone > $expectedUpper) {
        $string1 = $expected->format($formatString);
        $string2 = $actual->format($formatString);

        echo "Odd\n";
        echo $string1 . "\n";
        echo $string2 . "\n";
        exit(0);
    }

    if ($i % ($max / 100) === 0) {
        echo ".";
    }
    if ($i % ($max / 10) === 0) {
        echo "\n";
    }
}

echo "fin";


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-03-27 17:35 UTC] danack@php.net
-Status: Open +Status: Not a bug
 [2020-03-27 17:35 UTC] danack@php.net
PEBKAC.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Apr 28 13:01:29 2024 UTC