¿Debe MySQL tener su zona horaria configurada en UTC?

Pregunta de seguimiento de https://serverfault.com/questions/191331/should-servers-have-their-timezone-set-to-gmt-utc

¿La zona horaria de MySQL debe establecerse en UTC o debe configurarse para ser la misma zona horaria que el servidor o se establece PHP? (Si no es UTC)

¿Cuáles son los pros y los contras?

Parece que no importa qué zona horaria tenga el servidor, siempre que tenga el tiempo establecido para la zona horaria actual, conozca la zona horaria de las columnas de fecha y hora que almacena y tenga en cuenta los problemas con el horario de verano.

Por otro lado, si tiene el control de las zonas horarias de los servidores con los que trabaja, entonces puede tener todo configurado en UTC internamente y nunca preocuparse por las zonas horarias y el horario de verano.

Aquí hay algunas notas que recolecté de cómo trabajar con zonas horarias como una forma de hoja de trucos para mí y para otros que pueden influir en qué zona horaria elegirá la persona para su servidor y cómo almacenará la fecha y la hora.

MySQL Timezone Cheatsheet

Notas:

  1. El cambio de la zona horaria no cambiará la fecha y hora o la fecha y hora almacenadas , pero seleccionará una fecha y hora diferentes de las columnas de la marca de hora
  2. UTC no utiliza el horario de verano, GMT (la región) lo hace, GMT (la zona horaria) no (GMT también confunde la definición de segundos, por lo que se inventó UTC).
  3. ¡Advertencia! UTC tiene segundos intercalares, parecen ‘2012-06-30 23:59:60’ y se pueden agregar al azar, con 6 meses de anticipación, debido a la ralentización de la rotación de tierras
  4. ¡Advertencia! diferentes zonas horarias regionales pueden producir el mismo valor de fecha y hora debido al horario de verano
  5. La columna de marca de tiempo solo admite fechas de 1970-01-01 00:00:01 a 2038-01-19 03:14:07 UTC, debido a una limitación .
  6. Internamente, una columna de indicación de fecha y hora de MySQL se almacena como UTC, pero al seleccionar una fecha, MySQL la convertirá automáticamente a la zona horaria de la sesión actual.

    Al almacenar una fecha en una marca de tiempo, MySQL supondrá que la fecha está en la zona horaria de la sesión actual y la convertirá a UTC para el almacenamiento.

  7. MySQL puede almacenar fechas parciales en columnas de fecha y hora, estas se ven como “2013-00-00 04:00:00”
  8. MySQL almacena “0000-00-00 00:00:00” si establece una columna de fecha y hora como NULA, a menos que configure específicamente la columna para permitir nulo cuando la cree.
  9. Lee esto

Para seleccionar una columna de marca de tiempo en formato UTC

no importa en qué zona horaria esté la sesión actual de MySQL:

SELECT CONVERT_TZ(`timestamp_field`, @@session.time_zone, '+00:00') AS `utc_datetime` FROM `table_name` 

También puede configurar el servidor de sesión o la zona horaria de la sesión global o actual en UTC y luego seleccionar la marca de tiempo de la siguiente manera:

 SELECT `timestamp_field` FROM `table_name` 

Para seleccionar la fecha y hora actual en UTC:

 SELECT UTC_TIMESTAMP(); SELECT UTC_TIMESTAMP; SELECT CONVERT_TZ(NOW(), @@session.time_zone, '+00:00'); 

Ejemplo de resultado: 2015-03-24 17:02:41

Para seleccionar la fecha y hora actuales en la zona horaria de la sesión

 SELECT NOW(); SELECT CURRENT_TIMESTAMP; SELECT CURRENT_TIMESTAMP(); 

Para seleccionar la zona horaria que se configuró cuando se lanzó el servidor

 SELECT @@system_time_zone; 

Devuelve “MSK” o “+04: 00” para la hora de Moscú, por ejemplo, hay (o hubo) un error de MySQL donde, si se establece en una compensación numérica, no se ajusta el horario de verano

Para obtener la zona horaria actual

 SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP); 

Volverá a las 02:00:00 si tu zona horaria es +2: 00.

Para obtener la marca de tiempo de UNIX actual (en segundos):

 SELECT UNIX_TIMESTAMP(NOW()); SELECT UNIX_TIMESTAMP(); 

Para obtener la columna de marca de tiempo como una marca de tiempo UNIX

 SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name` 

Para obtener una columna de fecha y hora UTC como una marca de tiempo UNIX

 SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', @@session.time_zone)) FROM `table_name` 

Obtenga un huso horario actual de la zona horaria de un entero positivo de indicación de la hora de UNIX

 SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name` 

Obtenga una fecha y hora UTC de una marca de tiempo UNIX

 SELECT CONVERT_TZ(FROM_UNIXTIME(`unix_timestamp_int`), @@session.time_zone, '+00:00') FROM `table_name` 

Obtener un huso horario de la zona horaria actual de un entero de la marca de tiempo UNIX negativo

 SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND) 

Hay 3 lugares donde la zona horaria podría establecerse en MySQL:

Nota: Una zona horaria se puede establecer en 2 formatos:

  1. una compensación de UTC: ‘+00: 00’, ‘+10: 00’ o ‘-6: 00’
  2. como zona horaria con nombre: ‘Europa / Helsinki’, ‘US / Eastern’ o ‘MET’

Las zonas horarias con nombre solo se pueden usar si se han creado y llenado las tablas de información de la zona horaria en la base de datos mysql.

en el archivo “my.cnf”

 default_time_zone='+00:00' 

o

 timezone='UTC' 

@@ global.time_zone variable

Para ver en qué valor están configurados

 SELECT @@global.time_zone; 

Para establecer un valor para él, usa uno:

 SET GLOBAL time_zone = '+8:00'; SET GLOBAL time_zone = 'Europe/Helsinki'; SET @@global.time_zone='+00:00'; 

@@ session.time_zone variable

 SELECT @@session.time_zone; 

Para configurarlo, usa uno:

 SET time_zone = 'Europe/Helsinki'; SET time_zone = "+00:00"; SET @@session.time_zone = "+00:00"; 

tanto “@@ global.time_zone variable” como “@@ session.time_zone variable” pueden devolver “SYSTEM”, lo que significa que usan la zona horaria establecida en “my.cnf”.

Para que los nombres de la zona horaria funcionen (incluso para la zona horaria predeterminada) debe configurar las tablas de información de la zona horaria que se deben llenar: http://dev.mysql.com/doc/refman/5.1/en/time-zone-support. html

Nota: no puede hacer esto ya que devolverá NULL:

 SELECT CONVERT_TZ(`timestamp_field`, TIMEDIFF(NOW(), UTC_TIMESTAMP), '+00:00') AS `utc_datetime` FROM `table_name` 

Configurar tablas de zona horaria mysql

Para que CONVERT_TZ funcione, necesita que se llenen las tablas de la zona horaria

 SELECT * FROM mysql.`time_zone` ; SELECT * FROM mysql.`time_zone_leap_second` ; SELECT * FROM mysql.`time_zone_name` ; SELECT * FROM mysql.`time_zone_transition` ; SELECT * FROM mysql.`time_zone_transition_type` ; 

Si están vacíos, llénalos ejecutando este comando

 mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql 

si este comando le da el error ” data too long for column ‘abreviatura’ en la fila 1 “, entonces podría ser causado por un carácter NULL que se adjunta al final de la abreviación de la zona horaria

la solución es ejecutar esto

 mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql (if the above gives error "data too long for column 'abbreviation' at row 1") mysql_tzinfo_to_sql /usr/share/zoneinfo > /tmp/zut.sql echo "SET SESSION SQL_MODE = '';" > /tmp/mysql_tzinfo_to.sql cat /tmp/zut.sql >> /tmp/mysql_tzinfo_to.sql mysql --defaults-file=/etc/mysql/my.cnf --user=verifiedscratch -p mysql < /tmp/mysql_tzinfo_to.sql 

(asegúrese de que las reglas de su servidor estén actualizadas zdump -v Europe/Moscow | grep 2011 https://chrisjean.com/updating-daylight-saving-time-on-linux/ )

Consulte el historial de transición completo de DST (horario de verano) para cada zona horaria

 SELECT tzn.Name AS tz_name, tztt.Abbreviation AS tz_abbr, tztt.Is_DST AS is_dst, tztt.`Offset` AS `offset`, DATE_ADD('1970-01-01 00:00:00',INTERVAL tzt.Transition_time SECOND) AS transition_date FROM mysql.`time_zone_transition` tzt INNER JOIN mysql.`time_zone_transition_type` tztt USING(Time_zone_id, Transition_type_id) INNER JOIN mysql.`time_zone_name` tzn USING(Time_zone_id) -- WHERE tzn.Name LIKE 'Europe/Moscow' -- Moscow has weird DST changes ORDER BY tzt.Transition_time ASC 

CONVERT_TZ también aplica los cambios DST necesarios según las reglas de las tablas anteriores y la fecha que utiliza.

Nota:
Según los documentos , el valor que estableces para time_zone no cambia; si lo configuras como "+01: 00", por ejemplo, el time_zone se establecerá como un desplazamiento desde UTC, que no sigue al horario de verano, por lo que permanecer igual todo el año.

Solo las zonas horarias nombradas cambiarán el horario durante el horario de verano.

Las abreviaturas como CET siempre serán en invierno y CEST será en verano, mientras que +01: 00 siempre será hora UTC + 1 hora y ambas no cambiarán con el horario de verano.

La zona horaria del system será la zona horaria de la máquina host donde está instalado mysql (a menos que mysql no lo determine)

Puede leer más sobre cómo trabajar con DST aquí

preguntas relacionadas:

  • ¿Cómo configuro la zona horaria de MySQL?
  • MySql - SELECCIONE columna TimeStamp en formato UTC
  • ¿Cómo obtener la marca de tiempo de Unix en MySQL a partir de la hora UTC?
  • Convertir servidor MySQL TimeStamp a UTC
  • https://dba.stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp
  • ¿Cómo obtengo la zona horaria actual de MySQL?
  • Campos de fecha y hora de MySQL y horario de verano: ¿cómo hago referencia a la hora "extra"?
  • Conversión de valores negativos de FROM_UNIXTIME

Fuentes:

PHP y MySQL tienen sus propias configuraciones predeterminadas de zona horaria. Debe sincronizar el tiempo entre su base de datos y la aplicación web; de lo contrario, podría correr algunos problemas.

Lea este tutorial: Cómo sincronizar sus zonas horarias PHP y MySQL

Los pros y los contras son casi idénticos. Depende de si quieres esto o no.

Tenga cuidado, si la zona horaria de MySQL difiere de la hora de su sistema (por ejemplo, PHP), la comparación del tiempo o la impresión con el usuario implicará algunos retoques.