sql >> Base de Datos >  >> RDS >> Mysql

Uso de zonas horarias en una aplicación web PHP

Traté esta situación extensamente en una aplicación PHP/MySQL que escribí para un operador de aviones privados hace poco más de un año. Existen diferentes estrategias para manejar las zonas horarias en estas dos plataformas, pero explicaré cómo lo hice. Configuro el servidor MySQL en UTC y ejecuto cada secuencia de comandos PHP en la zona horaria que el usuario especifica durante el proceso de registro para el perfil de usuario.

MySQL y PHP (PHP 5.2 y superior) tienen tipos de datos de fecha y hora nativos. El datetime de MySQL es un tipo de datos primitivo, mientras que PHP 5.2 y superior ofrece el Clase de fecha y hora . El tipo de datos datetime de MySQL no incluye metadatos para la zona horaria, pero un objeto PHP DateTime siempre incluye una zona horaria. Si el constructor de fecha y hora de PHP no especifica la zona horaria opcional en el segundo argumento, entonces el constructor de fecha y hora de PHP usa la variable de entorno de php.

Tanto MySQL como PHP tienen una zona horaria predeterminada establecida en los archivos de configuración. MySQL usa el datetime establecido en el archivo de configuración para cada conexión de base de datos a menos que el usuario especifique una zona horaria diferente después de iniciar la conexión con el comando SET time_zone = [timezone]; . PHP también establece una variable de entorno de zona horaria para cada script usando la zona horaria establecida en el archivo de configuración del servidor, y esta variable de entorno se puede anular usando la función de PHP date_default_timezone_set() después de que comience el script.

La clase PHP DateTime tiene una propiedad llamada timezone , que es un objeto PHP DateTimeZone . El objeto DateTimeZone se especifica mediante una cadena para la zona horaria exacta. La lista de zonas horarias es completo, tiene cientos de zonas horarias individuales en todo el mundo. Las zonas horarias de PHP tendrán en cuenta el horario de verano automáticamente.

Cuando el usuario genera una fecha y hora en la aplicación web, construya un objeto PHP de fecha y hora en la zona horaria del perfil del usuario. Luego use el setTimezone método para modificar el objeto DateTime a la zona horaria UTC. Ahora tiene la fecha y hora del usuario en UTC y puede almacenar el valor en la base de datos. Usa el formato DateTime format método para expresar los datos como una cadena en el formato aceptado por MySQL.

Entonces, el usuario genera una fecha y hora, y usted crea un objeto PHP de fecha y hora en la zona horaria especificada por el usuario:

// set using an include file for user profile
$user_timezone = new DateTimeZone('America/New_York'); 

// 1st arg in format accepted by PHP strtotime
$date_object1 = new DateTime('8/9/2012 5:19 PM', $user_timezone); 
$date_object1->setTimezone(new DateTimeZone('UTC'));
$formated_string = $date_object1->format('Y-m-d H:i:s');
$query_string = "INSERT INTO `t_table1` (`datetime1`) VALUES('$formated_string')";

Cuando recupere el valor de la base de datos, construya en UTC y luego conviértalo a la zona horaria del usuario.

$query_string = "SELECT `datetime1` FROM `t_table1`";
$date_object1 = new DateTime($datetime_string_from_mysql, new DateTimeZone('UTC'));
$date_object1->setTimezone($user_timezone);
$string_for_display_in_application = $date_object1->format('m/d/Y g:i a');

Con este método, sus valores de fecha y hora siempre se almacenan en UTC dentro de la base de datos, y el usuario siempre experimenta los valores en la zona horaria de su perfil. PHP corregirá el horario de verano si es necesario para cada zona horaria.

Un problema:esta explicación no cubre el tipo de datos de marca de tiempo de MySQL. Recomiendo usar el tipo de fecha y hora de MySQL para almacenar valores de fecha y hora, no el tipo de datos de marca de tiempo. El tipo de datos de marca de tiempo se cubre en el manual aquí .

Editar: Puede producir una matriz que contenga cada cadena de zona horaria PHP usando listIdentifiers , que es un método estático de la clase DateTimeZone.