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:
-
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
-
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
-
GMT confonde i secondi, motivo per cui è stato inventato UTC.
-
Attenzione! fusi orari regionali diversi potrebbero produrre lo stesso valore datetime a causa dell'ora legale
-
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 .
-
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.
-
MySQL può memorizzare date parziali in colonne datetime, che sembrano "2013-00-00 04:00:00"
-
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.
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:
- Un offset da UTC:'+00:00', '+10:00' o '-6:00'
- 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:
- Come faccio a impostare il fuso orario di MySQL?
- MySql - SELEZIONA colonna TimeStamp in formato UTC
- Come ottenere un timestamp Unix in MySQL dall'ora UTC?
- Conversione del server MySQL TimeStamp in UTC
- https://dba. stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp
- Come si fa Ho il fuso orario corrente di MySQL?
- Campi MySQL datetime e ora legale:come faccio a fare riferimento all'ora "extra"?
- Conversione di valori negativi da FROM_UNIXTIME
Fonti:
- https://bugs.mysql.com/bug.php?id=68861
- http://dev. mysql.com/doc/refman/5.0/en/date-and-time-functions.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/ rant/MySQL-timezones.txt