¿Un objeto DateTime no está sujeto a su marca de tiempo? ¿O getTimestamp() tiene algún tipo de efecto secundario cuando se usa en el cambio de horario de verano?
Detalles
Al configurar la marca de tiempo de un objeto DateTime que está en DST de verano (lo que significa que la hora formateada existe tanto antes como después de cambiar el reloj), la marca de tiempo devuelta difiere de la marca de tiempo establecida.
$ php --version PHP 7.1.3 (cli) (built: Mar 17 2017 16:59:59) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies Reproducir
Considere el siguiente script php :
date_default_timezone_set('Europe/Berlin'); $date = new DateTime(); $set_timestamp = 1319932800; $date->setTimestamp($set_timestamp); $get_timestamp = $date->getTimestamp(); fwrite(STDERR, $set_timestamp . "\n"); // 1319932800 fwrite(STDERR, $get_timestamp . "\n"); // 1319936400 **(WHY IS THIS DIFFERENT?)**¿Por qué los valores impresos no son iguales?
El objeto \DateTime no mantiene las marcas de tiempo sino la hora local, y realiza conversiones en el captador de marcas de tiempo y el establecimiento de marcas de tiempo.
Da como resultado un efecto secundario una vez al año cuando se desactiva el horario de verano, ya que ambos rangos de marca de tiempo 1319932800..1319936400 y 1319936400..1319940000 se resuelven en la misma hora local:
https://www.epochconverter.com/timezones?q=1319936399&tz=Europe%2FBerlin https://www.epochconverter.com/timezones?q=1319939999&tz=Europe%2FBerlin
En primer lugar, la marca de tiempo de Unix siempre está en UTC, por lo que no tiene zona horaria ni horario de verano.
Por otro lado, el objeto DateTime almacena solo la hora local (el "local" significa qué zona horaria está configurada en la instancia de DateTime ) .
Por lo tanto, debe establecer la zona horaria en +00:00 o UTC antes de establecer una marca de tiempo para evitar conversiones de hora innecesarias y adivinar el horario de verano.
Tienes dos opciones:
DateTime El constructor anulará la zona horaria predeterminada y se establecerá explícitamente en +00:00 cuando obtenga la marca de tiempo (comenzó con @ ) en el primer parámetro:
$set_timestamp = 1319932800; $date = new DateTime('@' . $set_timestamp); print($set_timestamp . "\n"); print($date->getTimestamp() . "\n");Información: en este caso, el parámetro de zona horaria del constructor siempre se anulará.
setTimestamp() Llame setTimezone() con la zona horaria DateTimeZone('+00:00') o DateTimeZone('UTC') antes de llamar a setTimestamp() :
$set_timestamp = 1319932800; $date = new DateTime(); $date->setTimezone(new DateTimeZone('UTC')); $date->setTimestamp($set_timestamp); print($set_timestamp . "\n"); print($date->getTimestamp() . "\n");Por supuesto, en ambos casos la salida será:
1319932800 1319932800 El date_default_timezone_set() es innecesario en estos casos, porque no desea hacer nada con la hora local.
Sin embargo, cuando desee imprimir la $date en un formato legible por humanos (por lo tanto, cuando convierta la marca de tiempo de Unix a la hora local) , la zona horaria volverá a ser interesante.