sql >> Database >  >> RDS >> Mysql

MySQL datetime-velden en zomertijd -- hoe verwijs ik naar het extra uur?

Ik heb het bedacht voor mijn doeleinden. Ik zal samenvatten wat ik heb geleerd (sorry, deze aantekeningen zijn uitgebreid; ze zijn net zo goed bedoeld voor mijn toekomstige verwijzing als voor al het andere).

In tegenstelling tot wat ik in een van mijn eerdere opmerkingen zei, zijn DATETIME- en TIMESTAMP-velden doen anders gedragen. TIMESTAMP-velden (zoals de documenten aangeven) nemen wat u ze verzendt in de indeling "JJJJ-MM-DD uu:mm:ss" en converteren het van uw huidige tijdzone naar UTC-tijd. Het omgekeerde gebeurt transparant wanneer u de gegevens ophaalt. DATETIME-velden maken deze conversie niet. Ze nemen alles wat je ze stuurt en slaan het gewoon direct op.

Noch de veldtypen DATETIME noch de TIMESTAMP kunnen gegevens nauwkeurig opslaan in een tijdzone die DST in acht neemt . Als u "2009-11-01 01:30:00" opslaat, kunnen de velden niet onderscheiden welke versie van 1:30am u wilde -- de -04:00 of -05:00 versie.

Oké, dus we moeten onze gegevens opslaan in een niet-zomertijdzone (zoals UTC). TIMESTAMP-velden kunnen deze gegevens niet nauwkeurig verwerken om redenen die ik zal uitleggen:als uw systeem is ingesteld op een DST-tijdzone, is wat u in TIMESTAMP invoert misschien niet wat u eruit haalt. Zelfs als je het gegevens verzendt die je al naar UTC hebt geconverteerd, neemt het nog steeds aan dat de gegevens zich in je lokale tijdzone bevinden en doet het nog een conversie naar UTC. Deze door TIMESTAMP afgedwongen lokaal-naar-UTC-terug-naar-lokaal retourvlucht is verliesgevend wanneer uw lokale tijdzone DST observeert (sinds "2009-11-01 01:30:00" wordt toegewezen aan 2 verschillende mogelijke tijden).

Met DATETIME kunt u uw gegevens in elke gewenste tijdzone opslaan en erop vertrouwen dat u alles terugkrijgt wat u verzendt (u wordt niet gedwongen tot de verliesgevende retourconversies die TIMESTAMP-velden u opdringen). Dus de oplossing is om een ​​DATETIME-veld te gebruiken en voordat je opslaat in het veld converteer van uw systeemtijdzone naar een niet-DST-zone waarin u het wilt opslaan (ik denk dat UTC waarschijnlijk de beste optie is). Hierdoor kunt u de conversielogica in uw scripttaal inbouwen, zodat u expliciet het UTC-equivalent van "2009-11-01 01:30:00 -04:00" of ""2009-11-01 01:30:00 -05:00".

Een ander belangrijk ding om op te merken is dat de wiskundige functies voor datum/tijd van MySQL niet goed werken rond DST-grenzen als u uw datums opslaat in een DST TZ. Dus des te meer reden om in UTC op te slaan.

In een notendop doe ik nu dit:

Bij het ophalen van de gegevens uit de database:

Interpreteer de gegevens uit de database expliciet als UTC buiten MySQL om een ​​nauwkeurige Unix-tijdstempel te krijgen. Ik gebruik hiervoor de functie strtotime() van PHP of de klasse DateTime. Het kan niet op betrouwbare wijze worden gedaan binnen MySQL met behulp van MySQL's CONVERT_TZ() of UNIX_TIMESTAMP() functies omdat CONVERT_TZ alleen een 'YYYY-MM-DD hh:mm:ss' waarde zal uitvoeren die lijdt aan ambiguïteitsproblemen, en UNIX_TIMESTAMP() veronderstelt zijn invoer bevindt zich in de tijdzone van het systeem, niet de tijdzone waarin de gegevens WERKELIJK zijn opgeslagen (UTC).

Bij het opslaan van de gegevens in de database:

Converteer uw datum naar de exacte UTC-tijd die u wenst buiten MySQL. Bijvoorbeeld:met PHP's DateTime-klasse kunt u "2009-11-01 1:30:00 EST" duidelijk specificeren van "2009-11-01 1:30:00 EDT", en deze vervolgens converteren naar UTC en de juiste UTC-tijd opslaan naar uw DATETIME-veld.

Opluchting. Heel erg bedankt voor ieders input en hulp. Hopelijk bespaart dit iemand anders wat kopzorgen.

Trouwens, ik zie dit op MySQL 5.0.22 en 5.0.27



  1. Dichtstbijzijnde match, deel 1

  2. Hoe maak je een primaire sleutel in SQL

  3. MariaDB SCHEMA() uitgelegd

  4. Hoe het verschil in uren (decimaal) tussen twee datums in SQL Server te berekenen?