Me he encontrado con un problema al intentar calcular la cantidad de días entre dos fechas. Si la fecha de inicio es anterior al cambio de horario de verano, la cantidad de días se calcula incorrectamente.

A continuación se muestra una prueba rápida para reproducir el error:

/**
 * @dataProvider daysProvider
 */
public function testDays($start, $end, $expectedDays)
{
    $startDate = new \DateTime($start);
    $endDate = new \DateTime($end);
    $interval = $startDate->diff($endDate);
    $this->assertEquals($expectedDays, $interval->format('%a'));
}

/**
 * @dataProvider daysProvider
 */
public function testDaysSydney($start, $end, $expectedDays)
{
    $startDate = new \DateTime($start);
    $endDate = new \DateTime($end);
    $startDate->setTimezone(new \DateTimeZone('Australia/Sydney'));
    $endDate->setTimezone(new \DateTimeZone('Australia/Sydney'));
    $interval = $startDate->diff($endDate);
    $this->assertEquals($expectedDays, $interval->format('%a'));
}

public function daysProvider()
{
    return [
        ['2016-03-01', '2016-03-04', 3],
        ['2016-04-01', '2016-04-04', 3],
    ];
}

Y la salida:

PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

...F

Time: 23 ms, Memory: 4.00MB

There was 1 failure:

1) TimingTest::testDaysSydney with data set #1 ('2016-04-01', '2016-04-04', 3)
Failed asserting that '2' matches expected 3.

Encontré este informe de error: https://bugs.php.net/bug.php ? id = 63953 pero aparentemente se supone que el problema está solucionado.

¿Alguna idea de una solución para esto? Gracias

php
0
Marinus 15 feb. 2018 a las 10:24

2 respuestas

La mejor respuesta

Hay una diferencia entre configurar DateTimeZone a través del método DateTime setter (setTimezone) y configurarlo a través del constructor DateTime (como se indica en esta pregunta). Intente establecer la zona horaria a través del constructor:

public function testDaysSydney($start, $end, $expectedDays)
{
    $tz=new \DateTimeZone('Australia/Sydney');
    $startDate = new \DateTime($start, $tz);
    $endDate = new \DateTime($end, $tz);
    $interval = $startDate->diff($endDate);
    $this->assertEquals($expectedDays, $interval->format('%a'));
}
1
Dan Miller 15 feb. 2018 a las 08:13

Asegúrese de estar trabajando con la hora correcta.

1) Un método sería establecer la zona horaria en PHP en GMT o UTC en php.ini o usando date_default_timezone_set(). eso es lo que estas intentando

2) El otro enfoque sería usar gmdate() en lugar de date().

0
prakash tank 15 feb. 2018 a las 07:28