2012-02-19 21 views
7

Quería preguntar si esto iba a funcionar, antes de entrar en un refactor completo de cómo manejo las fechas y horas.Almacenamiento de fechas y horas en UTC y conversión de la hora local en PHP/MySQL

Para enmarcar mi pregunta, aquí está mi problema ... Almaceno "acciones" tomadas por el usuario en una tabla de historial. Estas acciones tienen una marca de tiempo en ellos. Los usuarios pueden ser de todo el mundo y, por lo tanto, tienen diferentes zonas horarias. Quiero mostrar los elementos en el historial y mostrar las marcas de tiempo en la zona horaria local.

Además, sé que puedo usar campos de fecha y hora y simplemente almacenar formatos de hora UTC, pero estoy optando por usar la marca de tiempo para que pueda establecer un valor predeterminado para la hora actual.

¿Funcionará para mi problema?

  1. Mi zona horaria del servidor será Los Ángeles

  2. marcas de tiempo tienda como una marca de tiempo en MySQL. Tengo entendido que la marca de tiempo siempre se almacena como UTC. Los registros se almacenarán de manera predeterminada como creation_date O estableceré explícitamente UTC_TIMESTAMP(). Eficazmente, todos los registros en el db serán UTC.

  3. Cuando un usuario inicia sesión, tomaré su zona horaria (la almaceno en el archivo db como configuración de usuario). Para este ejemplo, digamos que esta persona está en Nueva York.

Aquí es donde está mi pregunta. ¿Alguno de estos trabajos?

  1. a) Tome los datos del historial. Todas las marcas de tiempo se convertirán automáticamente de UTC a la hora de Los Ángeles. Elemento de historia de Foreach, convierta la marca de tiempo de Los Ángeles a Timestamp y eco de Nueva York.

O

  1. b) Establecer el php zona horaria "date_default_timezone_set" a Nueva York. Toma los datos del historial. Todas las marcas de tiempo son TODAVÍA en el tiempo de Los Angeles por el servidor todavía es tiempo de Los Ángeles. Elemento de historia de Foreach, solo repita la marca de tiempo porque "date_default_timezone_set" convertirá automáticamente la marca de tiempo de Los Angeles en Nueva York.

¿Funcionará la opción 4b? ¿Hay una mejor manera de convertir la hora de Los Ángeles a la hora de Nueva York?

¿Hay una mejor manera de hacer esto en general?

+3

Almacenar en UTC, mostrar local al usuario es la solución prevaleciente. –

Respuesta

5

Tiene razón, las marcas de tiempo de Unix siempre están en UTC. Si almacena las marcas de tiempo en su base de datos en UTC, todo lo que necesita hacer para generarlo en la hora local es cambiar la zona horaria en PHP a la zona horaria local para el usuario. No necesita hacer ninguna conversión en las marcas de tiempo.

<?php 

$timeStampFromDatabase = 1325448000; // 01 Jan 2012 20:00:00 GMT 

date_default_timezone_set('America/Los_Angeles'); 
echo date('r', $timeStampFromDatabase); // Sun, 01 Jan 2012 12:00:00 -0800 

date_default_timezone_set('Asia/Hong_Kong'); 
echo date('r', $timeStampFromDatabase); // Mon, 02 Jan 2012 04:00:00 +0800 

Puede cambiar su zona horaria sobre la marcha y siguen las marcas de tiempo de salida en un formato de fecha y van a ser "convertido" en base al conjunto zona horaria en PHP. Es muy fácil, no necesita hacer ningún manejo especial, y no importa dónde configure la zona horaria, siempre que lo haga antes de las fechas de salida, pero puede leerlas antes de configurar la zona horaria.

+1

'date_default_timezone_set' se usa para configurar la zona horaria predeterminada. No lo establecería más de una vez. Creo que es mejor crear un objeto 'DateTime' y usar' DateTime :: setTimezone() ': http://www.php.net/manual/en/function.date-timezone-set.php – CodeZombie

+0

Bueno, yo solo estaba cambiándolo para ilustrar el punto. Me imagino que solo se establecerá una vez en la aplicación, pero puede cambiarlo varias veces. Si tiene cuidado al cambiarlo, siempre puede cambiarlo y luego volver a cambiarlo a lo que era el valor anterior sin ningún problema. – drew010

+1

muchas gracias por la ayuda. pregunta un poco nueva con respecto a la función date_default_timezone_set. ¿Es esta una configuración que solo afecta al usuario actual o es una variable del sistema global? si es una var global, ¿no podría causar problemas entre todos los usuarios en diferentes zonas horarias? – jsheir

3

Desafortunadamente, "date_default_timezone_set" no funcionaba de la manera que pensé. Según el ejemplo anterior, funcionaría si las fechas con las que estaba trabajando ya estuvieran en el formato de marca de tiempo de Unix. Sin embargo, fueron formateados en "Y-m-d H: i: s" y lo único que cambiaría fue el desplazamiento GMT, que obviamente no funciona.

Después de algunas horas de inquietud, así es como pude manejar las conversiones de tiempo.

$datetime = new DateTime($date_to_convert); 
$usertimezone = new DateTimeZone($_SESSION['timezone']); //each user has their own timezone i store in a session (i.e. - "Americas/Los_Angeles") 
$datetime->setTimezone($usertimezone); 
echo $datetime->format("Y-m-d H:i:s"); 

supongo que podría haber hecho lo siguiente, así:

Pseudo code 
strtotime($datetime) 
date_default_timezone_set($user_timezone) 
echo date(format, $datetime) 

lo anterior, creo, obligaría a la función de la fecha de manejar que es lógica en el $ user_timezone dado. en retrospectiva, tendría que traducir cada $ datetime -> unix_timestamp -> $ datetime_converted, que no suena mucho mejor de lo que elegí hacer.

1

Siempre guarde sus marcas de tiempo en la base de datos como UTC. Esta es una zona horaria y punto independiente de horario de verano independiente. Para mostrar esto de nuevo al usuario en su zona horaria, sólo tiene que hacer:

$users_timezone = 'Europe/London'; // See PHP documentation for names that can be used. 
$date = new DateTime(); 
$date->setTimestamp($timestamp_from_database); 
$date->setTimezone(new DateTimeZone($users_timezone)); 
echo $date->format("H:ia jS F Y"); 
0

De manera predeterminada, las marcas de tiempo Unix siempre están en GMT. Si almacenamos las marcas de tiempo en nuestra base de datos en UTC, solo tenemos que utilizar la siguiente secuencia de comandos PHP:

<?php 

$TZ_UTC = new DateTimeZone('UTC'); //-->Database Timezone; 
$TZ_LOCAL = new DateTimeZone('America/New_York'); //-->Expected Local Timezone from user settings; 

//--Example Database Query-- 
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) { 
    //---If we want to show UTC timezone directy---- 
    echo $row['action_timestamp']; 

    //---If we want to show LOCAL timezone from user settings---- 
    $dateObj = new DateTime($row['action_timestamp'], $TZ_UTC); 
    $dateObj->setTimezone($TZ_LOCAL); //--> Here is the conversion! 
    echo $dateObj->format("Y-m-d H:i:s T"); 
} 
?> 
Cuestiones relacionadas