Mysql
 sql >> Database >  >> RDS >> Mysql

MySQL dovrebbe avere il suo fuso orario impostato su UTC?

Sembra che non importi quale sia il fuso orario sul server, purché tu abbia l'ora impostata correttamente per il fuso orario corrente, conosci il fuso orario delle colonne datetime che memorizzi e sei a conoscenza dei problemi con l'ora legale.

D'altra parte, se hai il controllo dei fusi orari dei server con cui lavori, puoi avere tutto impostato su UTC internamente e non preoccuparti mai dei fusi orari e dell'ora legale.

Ecco alcune note che ho raccolto su come lavorare con i fusi orari come una forma di cheatsheet per me stesso e per gli altri che potrebbero influenzare quale fuso orario la persona sceglierà per il proprio server e come memorizzerà data e ora.

Cheatsheet sul fuso orario di MySQL

Note:

  1. La modifica del fuso orario non modificherà la data e l'ora o il timestamp memorizzati , ma selezionerà una data e ora diversa dalle colonne timestamp

  2. Attenzione! L'UTC ha secondi intercalari, questi sembrano "2012-06-30 23:59:60" e possono essere aggiunti casualmente, con un preavviso di 6 mesi, a causa del rallentamento della rotazione terrestre

  3. GMT confonde i secondi, motivo per cui è stato inventato UTC.

  4. Attenzione! fusi orari regionali diversi potrebbero produrre lo stesso valore datetime a causa dell'ora legale

  5. La colonna timestamp supporta solo le date dal 1970-01-01 00:00:01 al 2038-01-19 03:14:07 UTC, a causa di una limitazione .

  6. Internamente una colonna timestamp MySQL è memorizzato come UTC ma quando si seleziona una data MySQL la convertirà automaticamente nel fuso orario della sessione corrente.

    Quando si memorizza una data in un timestamp, MySQL presumerà che la data sia nel fuso orario della sessione corrente e la convertirà in archiviazione UTC.

  7. MySQL può memorizzare date parziali in colonne datetime, che sembrano "2013-00-00 04:00:00"

  8. MySQL memorizza "0000-00-00 00:00:00" se imposti una colonna datetime come NULL, a meno che non imposti specificamente la colonna per consentire null quando la crei.

  9. Leggi questo

Per selezionare una colonna timestamp in formato UTC

indipendentemente dal fuso orario in cui si trova la sessione MySQL corrente:

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

Puoi anche impostare il fuso orario del server o della sessione globale o corrente su UTC e quindi selezionare il timestamp in questo modo:

SELECT `timestamp_field` FROM `table_name`

Per selezionare la data e l'ora corrente in UTC:

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

Esempio di risultato:2015-03-24 17:02:41

Per selezionare la data e l'ora corrente nel fuso orario della sessione

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

Per selezionare il fuso orario impostato all'avvio del server

SELECT @@system_time_zone;

Restituisce "MSK" o "+04:00" per l'ora di Mosca, ad esempio, c'è (o c'era) un bug di MySQL per cui se impostato su un offset numerico non regolerebbe l'ora legale

Per ottenere il fuso orario corrente

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);

Restituirà 02:00:00 se il tuo fuso orario è +2:00.

Per ottenere il timestamp UNIX corrente (in secondi):

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

Per ottenere la colonna timestamp come timestamp UNIX

SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`

Per ottenere una colonna data/ora UTC come timestamp UNIX

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

Ottieni un fuso orario datetime da un intero positivo di timestamp UNIX

SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`

Ottieni una data e ora UTC da un timestamp UNIX

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

Ottieni un fuso orario datetime da un numero intero negativo di timestamp UNIX

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

Ci sono 3 posti in cui il fuso orario potrebbe essere impostato in MySQL:

Nota:un fuso orario può essere impostato in 2 formati:

  1. Un offset da UTC:'+00:00', '+10:00' o '-6:00'
  2. come fuso orario con nome:'Europe/Helsinki', 'US/Eastern' o 'MET'

I fusi orari con nome possono essere utilizzati solo se le tabelle delle informazioni sui fusi orari nel database mysql sono state create e popolate.

nel file "my.cnf"

default_time_zone='+00:00'

o

timezone='UTC'

@@global.time_zone variabile

Per vedere a quale valore sono impostati

SELECT @@global.time_zone;

Per impostare un valore usa uno dei due:

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

@@session.time_zone variabile

SELECT @@session.time_zone;

Per impostarlo usa uno dei due:

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

sia "@@global.time_zone variable" che "@@session.time_zone variable" potrebbero restituire "SYSTEM", il che significa che usano il fuso orario impostato in "my.cnf".

Affinché i nomi dei fusi orari funzionino (anche per il fuso orario predefinito) è necessario impostare le tabelle delle informazioni sul fuso orario che devono essere compilate: http://dev.mysql.com/doc /refman/5.1/en/time-zone-support.html

Nota:non puoi farlo perché restituirà NULL:

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

Imposta tabelle di fuso orario MySQL

Per CONVERT_TZ per funzionare, è necessario che le tabelle dei fusi orari siano popolate

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` ;

Se sono vuoti, riempili eseguendo questo comando

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

se questo comando ti dà l'errore "dati troppo lunghi per la colonna 'abbreviazione' alla riga 1 ", potrebbe essere causato dall'aggiunta di un carattere NULL alla fine dell'abbreviazione del fuso orario

la soluzione è eseguire questo

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

(assicurati che le regole dst dei tuoi server siano aggiornate zdump -v Europe/Moscow | grep 2011 https://chrisjean.com/updating-daylight-saving-time- su Linux/ )

Visualizza la cronologia completa della transizione all'ora legale (DST) per ogni fuso orario

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 applica anche le modifiche necessarie all'ora legale in base alle regole nelle tabelle precedenti e alla data in cui utilizzi.

Nota:
Secondo i documenti , il valore impostato per time_zone non cambia, se ad esempio lo imposti come "+01:00", time_zone verrà impostato come offset dall'UTC, che non segue l'ora legale, quindi rimarrà lo stesso tutto tutto l'anno.

Solo i fusi orari denominati cambierà l'ora durante l'ora legale.

Abbreviazioni come CET sarà sempre un orario invernale e CEST sarà l'ora legale mentre +01:00 sarà sempre UTC tempo + 1 ora ed entrambi non cambieranno con l'ora legale.

Il system timezone sarà il fuso orario della macchina host su cui è installato mysql (a meno che mysql non riesca a determinarlo)

Puoi leggere ulteriori informazioni sull'utilizzo dell'ora legale qui

Quando non usare UTC dal leggendario Jon Skeet:https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/ (Ad esempio un evento programmato nel futuro che rappresenta un'ora, non un istante nel tempo)

domande correlate:

Fonti: