sql >> Databáze >  >> RDS >> Mysql

Pole data a času v MySQL a letní čas – jak mohu odkazovat na hodinu navíc?

Pro mé účely jsem to vymyslel. Shrnu, co jsem se naučil (omlouvám se, tyto poznámky jsou podrobné; jsou pro mé budoucí doporučení stejně jako cokoli jiného).

Na rozdíl od toho, co jsem řekl v jednom ze svých předchozích komentářů, pole DATETIME a TIMESTAMP provedou chovat se jinak. Pole TIMESTAMP (jak naznačují dokumenty) vezmou vše, co jim pošlete, ve formátu „RRRR-MM-DD hh:mm:ss“ a převedou to z vašeho aktuálního časového pásma na čas UTC. Opak se stane transparentně, kdykoli načtete data. Pole DATETIME tento převod neprovedou. Vezmou vše, co jim pošlete, a přímo to uloží.

Ani typy polí DATETIME ani TIMESTAMP nemohou přesně ukládat data v časovém pásmu, které dodržuje letní čas . Pokud uložíte „2009-11-01 01:30:00“, pole nijak nerozlišují, jakou verzi 1:30 jste chtěli – verzi -04:00 nebo -05:00.

Dobře, takže musíme ukládat naše data v časovém pásmu mimo letní čas (jako je UTC). Pole TIMESTAMP nejsou schopna zpracovat tato data přesně z důvodů, které vysvětlím:pokud je váš systém nastaven na časové pásmo DST, pak to, co vložíte do TIMESTAMP, nemusí být to, co dostanete zpět. I když mu pošlete data, která jste již převedli na UTC, bude stále předpokládat, že data jsou ve vašem místním časovém pásmu a provede další převod na UTC. Tato zpětná cesta z místa na místo UTC vynucená TIMESTAMPem je ztrátová, když vaše místní časové pásmo dodržuje letní čas (protože „2009-11-01 01:30:00“ mapuje 2 různé možné časy).

S DATETIME můžete svá data ukládat v libovolném časovém pásmu a mít jistotu, že dostanete zpět, cokoli pošlete (nebudete nuceni do ztrátových zpátečních konverzí, které vám pole TIMESTAMP vnucují). Řešením je tedy použít pole DATETIME a před uložením do pole převeďte z vašeho systémového časového pásma do libovolného pásma bez letního času, do kterého jej chcete uložit (myslím, že UTC je pravděpodobně nejlepší volbou). To vám umožní zabudovat konverzní logiku do vašeho skriptovacího jazyka, takže můžete explicitně uložit ekvivalent UTC „2009-11-01 01:30:00 -04:00“ nebo „“2009-11-01 01:30:00 -05:00".

Další důležitou věcí, kterou je třeba poznamenat, je, že matematické funkce data/času MySQL nefungují správně kolem hranic letního času, pokud svá data ukládáte do TZ letního času. Takže o důvod víc šetřit v UTC.

Stručně řečeno, teď dělám toto:

Při získávání dat z databáze:

Explicitně interpretujte data z databáze jako UTC mimo MySQL, abyste získali přesné unixové časové razítko. K tomu používám PHP funkci strtotime() nebo její třídu DateTime. Nelze to spolehlivě provést uvnitř MySQL pomocí funkcí CONVERT_TZ() nebo UNIX_TIMESTAMP() MySQL, protože CONVERT_TZ vydá pouze hodnotu 'YYYY-MM-DD hh:mm:ss', která trpí problémy s nejednoznačností, a UNIX_TIMESTAMP() předpokládá její vstup je v systémovém časovém pásmu, nikoli v časovém pásmu, ve kterém byla data SKUTEČNĚ uložena (UTC).

Při ukládání dat do databáze:

Převeďte své datum na přesný čas UTC, který si přejete mimo MySQL. Například:s třídou DateTime PHP můžete specifikovat „2009-11-01 1:30:00 EST“ odlišně od „2009-11-01 1:30:00 EDT“, poté jej převést na UTC a uložit správný čas UTC do pole DATETIME.

Fuj. Díky moc všem za příspěvky a pomoc. Doufejme, že to někomu jinému ušetří bolesti hlavy na cestě.

BTW, vidím to na MySQL 5.0.22 a 5.0.27



  1. UPSERT do tabulky s dynamickým názvem tabulky

  2. Přihlášení uživatele 'DOMAIN\MACHINENAME$' se nezdařilo

  3. Jak se EDB stala lídrem na trhu Postgres

  4. Jak opravím chybu „Poskytovatel pojmenovaných kanálů, chyba 40 – Nelze otevřít připojení k serveru SQL Server“?