Sembra che non importa quale fuso orario sia sul server, purché tu abbia il tempo impostato correttamente per il fuso orario corrente, conosci il fuso orario delle colonne del datetime che memorizzi e sei consapevole 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 e gli altri che potrebbero influenzare il fuso orario che la persona sceglierà per il suo server e come memorizzerà la data e l'ora.
MySQL Timezone Cheatsheet
Appunti:
- La modifica del fuso orario non cambierà il datetime o il timestamp memorizzati , ma selezionerà un datetime diverso dalle colonne timestamp
- Avvertimento! L'UTC ha secondi da saltare, questi sembrano "2012-06-30 23:59:60" e possono essere aggiunti in modo casuale, con un preavviso di 6 mesi, a causa del rallentamento della rotazione terrestre
GMT confonde i secondi, motivo per cui è stato inventato UTC.
Avvertimento! fusi orari regionali diversi potrebbero produrre lo stesso valore di data / ora 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 viene memorizzata 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 supporrà che la data sia nel fuso orario della sessione corrente e la converta in UTC per l'archiviazione.
- MySQL può memorizzare date parziali in colonne datetime, queste assomigliano a "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 la colonna specificatamente per consentire null quando la crei.
- Leggi questo
Per selezionare una colonna timestamp in formato UTC
indipendentemente dal fuso orario in cui si trova l'attuale sessione MySQL:
SELECT
CONVERT_TZ(`timestamp_field`, @@session.time_zone, '+00:00') AS `utc_datetime`
FROM `table_name`
Puoi anche impostare il fuso orario della sessione sever o globale o corrente su UTC e quindi selezionare il timestamp in questo modo:
SELECT `timestamp_field` FROM `table_name`
Per selezionare il datetime corrente in UTC:
SELECT UTC_TIMESTAMP();
SELECT UTC_TIMESTAMP;
SELECT CONVERT_TZ(NOW(), @@session.time_zone, '+00:00');
Risultato di esempio: 2015-03-24 17:02:41
Per selezionare il datetime 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 MySQL in 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 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 datetime UTC come data / ora UNIX
SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', @@session.time_zone)) FROM `table_name`
Ottieni un datetime di fuso orario corrente da un numero intero di data / ora UNIX positivo
SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`
Ottieni un datetime UTC da un timestamp UNIX
SELECT CONVERT_TZ(FROM_UNIXTIME(`unix_timestamp_int`), @@session.time_zone, '+00:00')
FROM `table_name`
Ottieni un datetime di fuso orario corrente da un numero intero di data / ora UNIX negativo
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 denominato: "Europa / Helsinki", "Stati Uniti / Est" o "MET"
I fusi orari nominati possono essere utilizzati solo se le tabelle di informazioni sul fuso orario nel database mysql sono state create e popolate.
nel file "my.cnf"
default_time_zone='+00:00'
o
timezone='UTC'
@@ variabile global.time_zone
Per vedere a quale valore sono impostati
SELECT @@global.time_zone;
Per impostare un valore per esso utilizzare 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 utilizzare uno dei due:
SET time_zone = 'Europe/Helsinki';
SET time_zone = "+00:00";
SET @@session.time_zone = "+00:00";
sia "@@ variabile globale.time_zone" che "@@ session.time_zone variabile" potrebbero restituire "SISTEMA", il che significa che usano il fuso orario impostato in "my.cnf".
Affinché i nomi di fuso orario funzionino (anche per il fuso orario predefinito) è necessario impostare le tabelle di informazioni sul fuso orario che devono essere popolate: http://dev.mysql.com/doc/refman/5.1/en/time-zone-support. html
Nota: non puoi farlo poiché restituirà NULL:
SELECT
CONVERT_TZ(`timestamp_field`, TIMEDIFF(NOW(), UTC_TIMESTAMP), '+00:00') AS `utc_datetime`
FROM `table_name`
Imposta le tabelle del fuso orario mysql
Per CONVERT_TZ
funzionare, è necessario compilare le tabelle del fuso orario
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 fornisce l'errore " dati troppo lunghi per la colonna" abbreviazione "nella riga 1 ", potrebbe essere causato da un carattere NULL che viene aggiunto alla fine dell'abbreviazione del fuso orario
la correzione è 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 del tuo server dst siano aggiornate zdump -v Europe/Moscow | grep 2011
https://chrisjean.com/updating-daylight-saving-time-on-linux/ )
Vedi la cronologia completa delle transizioni di ora legale (ora legale) 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 inoltre tutte le modifiche necessarie all'ora legale in base alle regole nelle tabelle sopra e alla data in uso.
Nota:
secondo i documenti , il valore impostato per time_zone non cambia, se lo si imposta come "+01: 00", ad esempio, allora time_zone verrà impostato come offset da UTC, che non segue l'ora legale, quindi rimarrà lo stesso tutto l'anno.
Solo i fusi orari indicati cambieranno l'ora durante l'ora legale.
Abbreviazioni come CET
sarà sempre un orario invernale e CEST
sarà l' UTC
ora legale mentre +01: 00 sarà sempre l' ora + 1 ora ed entrambe non cambieranno con l'ora legale.
Il system
fuso orario sarà il fuso orario della macchina host in cui è installato mysql (a meno che mysql non riesca a determinarlo)
Puoi leggere di più su come lavorare con l'ora legale qui
domande correlate:
fonti: