Parece que no importa qué zona horaria esté en el servidor, siempre que tenga la hora establecida correctamente para la zona horaria actual, conozca la zona horaria de las columnas de fecha y hora que almacena y esté al tanto de 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, puede tener todo configurado en UTC internamente y nunca preocuparse por las zonas horarias y el horario de verano.
Aquí hay algunas notas que recopilé sobre cómo trabajar con zonas horarias como una forma de hoja de trucos para mí y para otros que podrían influir en qué zona horaria elegirá la persona para su servidor y cómo almacenará la fecha y la hora.
Hoja de trucos de zona horaria de MySQL
Notas:
-
Cambiar la zona horaria no cambiará la fecha y la hora almacenadas , pero seleccionará una fecha y hora diferente de las columnas de marca de tiempo
-
¡Advertencia! UTC tiene segundos bisiestos, estos parecen '2012-06-30 23:59:60' y se pueden agregar al azar, con 6 meses de anticipación, debido a la desaceleración de la rotación de la tierra
-
GMT confunde segundos, razón por la cual se inventó UTC.
-
¡Advertencia! diferentes zonas horarias regionales pueden producir el mismo valor de fecha y hora debido al horario de verano
-
La columna de marca de tiempo solo admite fechas 1970-01-01 00:00:01 a 2038-01-19 03:14:07 UTC, debido a una limitación .
-
Internamente, una columna de marca de tiempo 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 asumirá que la fecha está en la zona horaria de la sesión actual y la convertirá a UTC para el almacenamiento.
-
MySQL puede almacenar fechas parciales en columnas de fecha y hora, estas parecen "2013-00-00 04:00:00"
-
MySQL almacena "0000-00-00 00:00:00" si configura una columna de fecha y hora como NULL, a menos que configure específicamente la columna para permitir nulo cuando la cree.
Para seleccionar una columna de marca de tiempo en formato UTC
no importa en qué zona horaria se encuentre 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 la zona horaria del servidor, global o de la sesión 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');
Resultado de ejemplo:2015-03-24 17:02:41
Para seleccionar la fecha y hora actual 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 había) un error de MySQL en el que, si se establece en un desplazamiento numérico, no se ajustaría el horario de verano
Para obtener la zona horaria actual
SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);
Volverá a las 02:00:00 si su zona horaria es +2:00.
Para obtener la marca de tiempo 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`
Obtener una fecha y hora de la zona horaria actual a partir de un entero de marca de tiempo UNIX positivo
SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`
Obtener 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 una fecha y hora de la zona horaria actual a partir de un entero de marca de tiempo UNIX negativo
SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND)
Hay 3 lugares donde se puede establecer la zona horaria en MySQL:
Nota:una zona horaria se puede establecer en 2 formatos:
- un desplazamiento de UTC:'+00:00', '+10:00' o '-6:00'
- como una zona horaria con nombre:'Europa/Helsinki', 'EE. UU./Este' o 'MET'
Las zonas horarias con nombre solo se pueden usar si las tablas de información de zonas horarias en la base de datos mysql se han creado y completado.
en el archivo "mi.cnf"
default_time_zone='+00:00'
o
timezone='UTC'
@@variable global.time_zone
Para ver en qué valor están configurados
SELECT @@global.time_zone;
Para establecer un valor, use cualquiera de los dos:
SET GLOBAL time_zone = '+8:00';
SET GLOBAL time_zone = 'Europe/Helsinki';
SET @@global.time_zone='+00:00';
@@sesión.variable de zona horaria
SELECT @@session.time_zone;
Para configurarlo, use cualquiera de los dos:
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 configurada en "my.cnf".
Para que los nombres de las zonas horarias funcionen (incluso para la zona horaria predeterminada), debe configurar las tablas de información de la zona horaria que deben completarse: 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 CONVERT_TZ
para trabajar, necesita que las tablas de zonas horarias estén completas
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énelos ejecutando este comando
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
si este comando le da el error "datos demasiado largos para la columna 'abreviatura' en la fila 1 ", entonces podría deberse a que se agrega un carácter NULL al final de la abreviatura 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 horario de verano de sus servidores estén actualizadas zdump -v Europe/Moscow | grep 2011
https://chrisjean.com/actualizando-el-horario-de-ahorro- en Linux/
)
Vea el historial de transición DST (horario de verano) completo 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 cualquier cambio de horario de verano necesario según las reglas de las tablas anteriores y la fecha que usa.
Según los docs , el valor que establece para time_zone no cambia, si lo establece como "+01:00", por ejemplo, time_zone se establecerá como un desplazamiento de UTC, que no sigue el horario de verano, por lo que permanecerá igual todo el tiempo. todo el año.
Solo las zonas horarias nombradas cambiará la hora durante el horario de verano.
Abreviaturas como CET
siempre será un horario de invierno y CEST
será horario de verano mientras que +01:00 siempre será UTC
tiempo + 1 hora y ambos no cambiarán con DST.
El system
zona horaria será la zona horaria de la máquina host donde está instalado mysql (a menos que mysql no pueda determinarlo)
Puede leer más sobre cómo trabajar con DST aquí
Cuándo no usar UTC por el legendario Jon Skeet:https://codeblog.jonskeet.uk/2019/03/27/almacenar-utc-no-es-una-bala-de-plata/ (Por ejemplo, un evento programado en el futuro que representa una hora, no un instante en el tiempo)
preguntas relacionadas:
- ¿Cómo configuro la zona horaria de MySQL?
- MySql - Columna SELECCIONAR marca de tiempo en formato UTC
- Cómo obtener la marca de tiempo de Unix en MySQL desde la hora UTC?
- Convertir la marca de tiempo MySQL del servidor 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"?
- Convertir valores negativos de FROM_UNIXTIME
Fuentes:
- https://bugs.mysql.com/bug.php?id=68861
- http://dev. mysql.com/doc/refman/5.0/en/fecha-y-hora-funciones.html
- http://dev.mysql.com/doc/ refman/5.1/en/datetime.html
- http://en.wikipedia.org/wiki/Coordinated_Universal_Time
- http://shafiqissani.wordpress.com/2010/09/30/how-to-get-the-current-epoch-time-unix-timestamp/
- https://web.ivy.net/~carton/ despotricar/MySQL-timezones.txt