Det verkar som att det inte spelar någon roll vilken tidszon som finns på servern så länge du har rätt tid inställd för den aktuella tidszonen, känner till tidszonen för datetime-kolumnerna som du lagrar och är medveten om problemen med sommartid.
Å andra sidan om du har kontroll över tidszonerna för de servrar du arbetar med kan du ha allt inställt på UTC internt och aldrig oroa dig för tidszoner och sommartid.
Här är några anteckningar som jag samlat in om hur man arbetar med tidszoner som en form av cheatsheet för mig själv och andra som kan påverka vilken tidszon personen kommer att välja för sin server och hur han/hon kommer att lagra datum och tid.
MySQL Timezone Cheatsheet
Anmärkningar:
-
Att ändra tidszonen kommer inte att ändra den lagrade datum- och tidsstämpeln , men det kommer att välja ett annat datum och tid från tidsstämpelkolumnerna
-
Varning! UTC har skottsekunder, dessa ser ut som '2012-06-30 23:59:60' och kan läggas till slumpmässigt, med 6 månaders varsel, på grund av att jordens rotation saktar ner
-
GMT förvirrar sekunder, vilket är anledningen till att UTC uppfanns.
-
Varning! olika regionala tidszoner kan ge samma datum och tid på grund av sommartid
-
Tidstämpelkolumnen stöder endast datum 1970-01-01 00:00:01 till 2038-01-19 03:14:07 UTC, på grund av en begränsning .
-
Internt en MySQL-tidsstämpelkolumn lagras som UTC men när du väljer ett datum kommer MySQL automatiskt att konvertera det till den aktuella sessionens tidszon.
När du lagrar ett datum i en tidsstämpel antar MySQL att datumet är i den aktuella sessionens tidszon och konverterar det till UTC för lagring.
-
MySQL kan lagra partiella datum i datetime-kolumner, dessa ser ut som"2013-00-00 04:00:00"
-
MySQL lagrar "0000-00-00 00:00:00" om du ställer in en datetime-kolumn som NULL, om du inte specifikt ställer in kolumnen så att den tillåter null när du skapar den.
För att välja en tidsstämpelskolumn i UTC-format
oavsett vilken tidszon den aktuella MySQL-sessionen är i:
SELECT
CONVERT_TZ(`timestamp_field`, @@session.time_zone, '+00:00') AS `utc_datetime`
FROM `table_name`
Du kan också ställa in servern eller den globala eller aktuella sessionens tidszon till UTC och sedan välja tidsstämpeln så här:
SELECT `timestamp_field` FROM `table_name`
För att välja aktuell datumtid i UTC:
SELECT UTC_TIMESTAMP();
SELECT UTC_TIMESTAMP;
SELECT CONVERT_TZ(NOW(), @@session.time_zone, '+00:00');
Exempelresultat:2015-03-24 17:02:41
För att välja aktuell datumtid i sessionens tidszon
SELECT NOW();
SELECT CURRENT_TIMESTAMP;
SELECT CURRENT_TIMESTAMP();
För att välja den tidszon som ställdes in när servern startade
SELECT @@system_time_zone;
Returnerar "MSK" eller "+04:00" för Moskva-tid till exempel, det finns (eller fanns) en MySQL-bugg där om den ställdes till en numerisk offset inte skulle justera sommartiden
För att få aktuell tidszon
SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);
Den kommer tillbaka 02:00:00 om din tidszon är +2:00.
För att få den aktuella UNIX-tidsstämpeln (i sekunder):
SELECT UNIX_TIMESTAMP(NOW());
SELECT UNIX_TIMESTAMP();
För att få tidsstämpelkolumnen som en UNIX-tidsstämpel
SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`
För att få en UTC-datumtidkolumn som en UNIX-tidsstämpel
SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', @@session.time_zone)) FROM `table_name`
Få en aktuell tidszon datumtid från ett positivt UNIX-tidsstämpeltal
SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`
Få en UTC-datumtid från en UNIX-tidsstämpel
SELECT CONVERT_TZ(FROM_UNIXTIME(`unix_timestamp_int`), @@session.time_zone, '+00:00')
FROM `table_name`
Få en aktuell tidszon datumtid från ett negativt UNIX-tidsstämpeltal
SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND)
Det finns tre platser där tidszonen kan ställas in i MySQL:
Obs:En tidszon kan ställas in i två format:
- en offset från UTC:'+00:00', '+10:00' eller '-6:00'
- som en namngiven tidszon:'Europe/Helsingfors', 'US/Eastern' eller 'MET'
Namngivna tidszoner kan endast användas om tidszonsinformationstabellerna i mysql-databasen har skapats och fyllts i.
i filen "my.cnf"
default_time_zone='+00:00'
eller
timezone='UTC'
@@global.time_zone variabel
För att se vilket värde de är inställda på
SELECT @@global.time_zone;
För att ställa in ett värde för det, använd endera:
SET GLOBAL time_zone = '+8:00';
SET GLOBAL time_zone = 'Europe/Helsinki';
SET @@global.time_zone='+00:00';
@@session.time_zone variabel
SELECT @@session.time_zone;
För att ställa in det, använd endera:
SET time_zone = 'Europe/Helsinki';
SET time_zone = "+00:00";
SET @@session.time_zone = "+00:00";
både "@@global.time_zone variabel" och "@@session.time_zone variabel" kan returnera "SYSTEM" vilket betyder att de använder tidszonen som är inställd i "my.cnf".
För att tidszonnamn ska fungera (även för standardtidszon) måste du ställa in dina tidszonsinformationstabeller måste fyllas i: http://dev.mysql.com/doc /refman/5.1/en/time-zone-support.html
Obs:du kan inte göra detta eftersom det kommer att returnera NULL:
SELECT
CONVERT_TZ(`timestamp_field`, TIMEDIFF(NOW(), UTC_TIMESTAMP), '+00:00') AS `utc_datetime`
FROM `table_name`
Ställ in mysql-tidszonstabeller
För CONVERT_TZ
för att fungera måste du fylla i tidszonstabellerna
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` ;
Om de är tomma, fyll sedan i dem genom att köra det här kommandot
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
om detta kommando ger dig felet "data för lång för kolumn 'förkortning' på rad 1 ", då kan det bero på att ett NULL-tecken läggs till i slutet av tidszonens förkortning
korrigeringen är att köra detta
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
(se till att dina servrars dst-regler är uppdaterade zdump -v Europe/Moscow | grep 2011
https://chrisjean.com/updating-daylight-saving-time- on-linux/
)
Se hela övergångshistoriken för sommartid (sommartid) för varje tidszon
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
tillämpar även alla nödvändiga ändringar i sommartid baserat på reglerna i ovanstående tabeller och datumet som du använder.
Obs!
Enligt dokumenten , värdet du anger för tidszon ändras inte, om du ställer in det som "+01:00" till exempel, kommer tidszonen att ställas in som en offset från UTC, som inte följer sommartid, så den kommer att förbli densamma alla året runt.
Endast de namngivna tidszonerna kommer att ändra tid under sommartid.
Förkortningar som CET
kommer alltid att vara en vintertid och CEST
kommer att vara sommartid medan +01:00 alltid kommer att vara UTC
tid + 1 timme och båda ändras inte med sommartid.
system
tidszon kommer att vara tidszonen för värddatorn där mysql är installerat (såvida inte mysql inte kan fastställa det)
Du kan läsa mer om att arbeta med sommartid här
När ska man inte använda UTC av den legendariska Jon Skeet:https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/ (Till exempel en schemalagd händelse i framtiden som representerar en tid, inte ett ögonblick i tiden)
relaterade frågor:
- Hur ställer jag in tidszonen för MySQL?
- MySql - VÄLJ TimeStamp Column i UTC-format
- Hur man få Unix-tidsstämpel i MySQL från UTC-tid?
- Konvertera Server MySQL TimeStamp till UTC
- https://dba. stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp
- Hur gör Jag får den aktuella tidszonen för MySQL?
- MySQL datetime-fält och sommartid -- hur refererar jag till den "extra" timmen?
- Konvertera negativa värden från FROM_UNIXTIME
Källor:
- 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