Skip to content

DateTime::diff doesnt evaluate daylight saving time correctly  #9382

Closed

Description

@chaosben

Description

The following code:

<?php

$dt1 = new DateTime('2022-08-01 07:00:00', new DateTimeZone('Europe/Berlin'));
$dt2 = new DateTime('2022-08-01 07:00:00 +02:00');

echo "DT1: {$dt1->format('c')}" . PHP_EOL;
echo "DT2: {$dt2->format('c')}" . PHP_EOL;

$diff = $dt1->diff($dt2);

echo "Diff: {$diff->format('%h')}";

Resulted in this output:

DT1: 2022-08-01T07:00:00+02:00
DT2: 2022-08-01T07:00:00+02:00
Diff: 1

But I expected this output instead:

DT1: 2022-08-01T07:00:00+02:00
DT2: 2022-08-01T07:00:00+02:00
Diff: 0

According to https://3v4l.org/eOUP5 this bug exists since PHP 8.1.0

PHP Version

PHP 8.1.9

Operating System

Fedora 36

Activity

  1. cmb69 commented on Aug 19, 2022

    @cmb69
    Member

    Indeed, that looks wrong to me.

  2. hormus commented on Aug 20, 2022

    @hormus

    @cmb69 @derickr forgot to add a note in the manual for diff, if they are with timezone type int 3 the result is effective otherwise if different timezones will be converted to UTC and calculate the difference. if you need I will send you when diff has been modified.

    yes it's a bug for me too

    Valid period transitions:

    <?php
    
    date_default_timezone_set('Europe/Berlin');
    $origin = new DateTime('2022-03-27 02:00:00', new DateTimeZone('Europe/Berlin'));
    $target = new DateTime('2022-03-27 02:00:00 +0200');
    $origin->setTimeZone(new DateTimeZone('Europe/Berlin'));
    $origin = new DateTime($origin->format('Y-m-d H:i:s'), new DateTimeZone('Europe/Berlin'));
    
    $simil_utc = $target->format('Y-m-d H:i:s');
    $target = new DateTime($simil_utc, new DateTimeZone('Europe/Berlin'));
    $target->setTimeZone(new DateTimeZone('Europe/Berlin'));
    $target = new DateTime($target->format('Y-m-d H:i:s'), new DateTimeZone('Europe/Berlin'));
    $interval = $origin->diff($target);
    
    echo $interval->format('%R%a days %h hours') . "\n";
    var_dump($origin, $target);
    
    ?>

    DateTime::Diff php 8.10 > if object same type offset timezone $origin and $target is local time object. Means for DST +0200: Europe/Berlin = Europe/Berlin or Europe/Berlin = +0200 or Europe/Berlin = CEST (ex. Localtime object 2022-03-27 02:00:00 - 2022-03-27 02:00:00 = 0 or 2022-03-27 03:00:00 - 2022-03-27 03:00:00 = 0 or Europe/Berlin = +0200 2022-03-27 03:00:00 - 2022-03-27 02:00:00 = 0), for Europe/Berlin: ST (+0100) and DST (+0200) 2022-03-27 01:00:00 - 2022-03-27 03:00:00 = 1 or 2022-03-27 01:00:00 - 2022-03-27 02:00:00 = 1
    Note* for ST type 3 and DST type 1: besides the bug mentioned Diff does not support several transitions. In all other cases it converts it to UTC.
    DateTime::Diff php 5.3.0 < php 8.1.0 $origin and $target is UTC object. Europe/Berlin to UTC. Means: (ex. UTC object 2022-03-27 01:00:00 - 2022-03-27 01:00:00 = 0)

  3. derickr commented on Aug 25, 2022

    @derickr
    Member

    This seems to be already fixed in the 8.1.10RC1. I can successfully recreate this with 8.1.9, but not with 8.1.10RC1. I believe it is a duplicate of #8730.

  4. chaosben commented on Aug 25, 2022

    @chaosben
    Author

    🥳 Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions