Zdá se, že nezáleží na tom, jaké časové pásmo je na serveru, pokud máte správně nastavený čas pro aktuální časové pásmo, znáte časové pásmo ve sloupcích datetime, které ukládáte, a jste si vědomi problémů s letním časem.
Na druhou stranu, pokud máte kontrolu nad časovými pásmy serverů, se kterými pracujete, můžete mít vše interně nastaveno na UTC a nemusíte se nikdy starat o časová pásma a letní čas.
Zde je několik poznámek, které jsem shromáždil o tom, jak pracovat s časovými pásmy jako formou cheatsheetu pro mě a ostatní, které mohou ovlivnit, jaké časové pásmo si uživatel vybere pro svůj server a jak bude ukládat datum a čas.
Chatová tabulka časového pásma MySQL
Poznámky:
-
Změna časového pásma nezmění uložené datum a čas nebo časové razítko , ale vybere jiné datum a čas ze sloupců časového razítka
-
Upozornění! UTC má přestupné sekundy, ty vypadají jako '2012-06-30 23:59:60' a mohou být přidány náhodně, s upozorněním 6 měsíců předem, kvůli zpomalení rotace Země
-
GMT mate sekundy, a proto bylo vynalezeno UTC.
-
Upozornění! různá regionální časová pásma mohou mít stejnou hodnotu data a času kvůli letnímu času
-
Sloupec časového razítka podporuje pouze data 1970-01-01 00:00:01 až 2038-01-19 03:14:07 UTC, kvůli omezení .
-
Interně sloupec časového razítka MySQL je uloženo jako UTC ale když vyberete datum, MySQL jej automaticky převede na časové pásmo aktuální relace.
Při ukládání data do časového razítka bude MySQL předpokládat, že datum je v aktuálním časovém pásmu relace a převede ho na UTC pro uložení.
-
MySQL může ukládat částečná data do sloupců data a času, ty vypadají jako "2013-00-00 04:00:00"
-
MySQL ukládá "0000-00-00 00:00:00", pokud nastavíte sloupec datetime jako NULL, pokud sloupec výslovně nenastavíte tak, aby při jeho vytvoření umožňoval hodnotu null.
Výběr sloupce časového razítka ve formátu UTC
bez ohledu na to, v jakém časovém pásmu se aktuální relace MySQL nachází:
SELECT
CONVERT_TZ(`timestamp_field`, @@session.time_zone, '+00:00') AS `utc_datetime`
FROM `table_name`
Můžete také nastavit časové pásmo serveru nebo globální nebo aktuální časové pásmo relace na UTC a poté vybrat časové razítko takto:
SELECT `timestamp_field` FROM `table_name`
Výběr aktuálního data a času v UTC:
SELECT UTC_TIMESTAMP();
SELECT UTC_TIMESTAMP;
SELECT CONVERT_TZ(NOW(), @@session.time_zone, '+00:00');
Příklad výsledku:2015-03-24 17:02:41
Výběr aktuálního data a času v časovém pásmu relace
SELECT NOW();
SELECT CURRENT_TIMESTAMP;
SELECT CURRENT_TIMESTAMP();
Výběr časového pásma, které bylo nastaveno při spuštění serveru
SELECT @@system_time_zone;
Vrací „MSK“ nebo „+04:00“ pro moskevský čas, například existuje (nebo byla) chyba MySQL, kde nastavení na číselný posun neupraví letní čas
Získání aktuálního časového pásma
SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);
Pokud je vaše časové pásmo +2:00, vrátí se 02:00:00.
Chcete-li získat aktuální časové razítko UNIX (v sekundách):
SELECT UNIX_TIMESTAMP(NOW());
SELECT UNIX_TIMESTAMP();
Chcete-li získat sloupec časového razítka jako časové razítko UNIX
SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`
Chcete-li získat sloupec data a času UTC jako časové razítko UNIX
SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', @@session.time_zone)) FROM `table_name`
Získejte aktuální datum a čas časového pásma z kladného celého čísla časového razítka UNIX
SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`
Získejte datum a čas UTC z časového razítka UNIX
SELECT CONVERT_TZ(FROM_UNIXTIME(`unix_timestamp_int`), @@session.time_zone, '+00:00')
FROM `table_name`
Získejte aktuální datum a čas časového pásma ze záporného celého čísla časového razítka UNIX
SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND)
Existují 3 místa, kde lze v MySQL nastavit časové pásmo:
Poznámka:Časové pásmo lze nastavit ve 2 formátech:
- posun od UTC:'+00:00', '+10:00' nebo '-6:00'
- jako pojmenované časové pásmo:„Europe/Helsinki“, „US/Eastern“ nebo „MET“
Pojmenovaná časová pásma lze použít pouze v případě, že byly vytvořeny a naplněny informační tabulky časových pásem v databázi mysql.
v souboru "my.cnf"
default_time_zone='+00:00'
nebo
timezone='UTC'
@@global.time_zone variable
Chcete-li zjistit, na jakou hodnotu jsou nastaveny
SELECT @@global.time_zone;
Chcete-li pro něj nastavit hodnotu, použijte jednu z následujících možností:
SET GLOBAL time_zone = '+8:00';
SET GLOBAL time_zone = 'Europe/Helsinki';
SET @@global.time_zone='+00:00';
proměnná @session.time_zone
SELECT @@session.time_zone;
Chcete-li jej nastavit, použijte jednu z následujících možností:
SET time_zone = 'Europe/Helsinki';
SET time_zone = "+00:00";
SET @@session.time_zone = "+00:00";
jak "@@global.time_zone variable" tak "@@session.time_zone variable" mohou vrátit "SYSTEM", což znamená, že používají časové pásmo nastavené v "my.cnf".
Aby názvy časových pásem fungovaly (i pro výchozí časové pásmo), musíte nastavit, aby tabulky s informacemi o časových pásmech byly vyplněny: http://dev.mysql.com/doc /refman/5.1/en/time-zone-support.html
Poznámka:Toto nemůžete udělat, protože to vrátí NULL:
SELECT
CONVERT_TZ(`timestamp_field`, TIMEDIFF(NOW(), UTC_TIMESTAMP), '+00:00') AS `utc_datetime`
FROM `table_name`
Nastavení tabulek časových pásem mysql
Pro CONVERT_TZ
Chcete-li pracovat, potřebujete, aby byly vyplněny tabulky časových pásem
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` ;
Pokud jsou prázdné, vyplňte je spuštěním tohoto příkazu
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
pokud vám tento příkaz zobrazí chybu "data jsou příliš dlouhá pro sloupec 'zkratka' na řádku 1 ", pak to může být způsobeno znakem NULL připojeným na konec zkratky časového pásma
opravou je spuštění tohoto
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
(ujistěte se, že jsou pravidla dst vašich serverů aktuální zdump -v Europe/Moscow | grep 2011
https://chrisjean.com/updating-daylight-saving-time- on-linux/
)
Zobrazit úplnou historii přechodu DST (letního času) pro každé časové pásmo
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
také použije všechny nezbytné změny DST na základě pravidel ve výše uvedených tabulkách a data, které používáte.
Poznámka:
Podle dokumentů , hodnota, kterou jste nastavili pro time_zone, se nezmění, pokud ji nastavíte například jako "+01:00", pak time_zone bude nastaveno jako offset od UTC, které nesleduje DST, takže zůstane stejné. celoročně.
Pouze vyjmenovaná časová pásma změní čas během letního času.
Zkratky jako CET
bude vždy zimní čas a CEST
bude letní čas, zatímco +01:00 bude vždy UTC
čas + 1 hodina a obě se s DST nezmění.
system
timezone bude časové pásmo hostitelského počítače, kde je nainstalován mysql (pokud ho mysql nedokáže určit)
Další informace o práci s DST si můžete přečíst zde
Kdy nepoužívat UTC od legendárního Jona Skeeta:https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/ (Například plánovaná událost v budoucnosti, která představuje čas, nikoli okamžik v čase)
související otázky:
- Jak nastavím časové pásmo MySQL?
- MySql – SELECT TimeStamp Column ve formátu UTC
- Jak na to získat unixové časové razítko v MySQL z času UTC?
- Převod časového razítka serveru MySQL na UTC
- https://dba. stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp
- Jak Dostanu aktuální časové pásmo MySQL?
- Pole data a času MySQL a letní čas – jak mohu uvést „hodinu navíc“?
- Převod záporných hodnot z FROM_UNIXTIME
Zdroje:
- 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