sql >> Databasteknik >  >> RDS >> Mysql

MySQL datetime-fält och sommartid -- hur refererar jag till den extra timmen?

Jag har kommit på det för mina syften. Jag ska sammanfatta vad jag lärde mig (förlåt, dessa anteckningar är mångsidiga, de är lika mycket för min framtida remiss som allt annat).

I motsats till vad jag sa i en av mina tidigare kommentarer, gör fälten DATETIME och TIMESTAMP bete sig annorlunda. TIMESTAMP-fälten (som dokumenten indikerar) tar vad du än skickar dem i "ÅÅÅÅ-MM-DD hh:mm:ss"-format och konverterar det från din nuvarande tidszon till UTC-tid. Det omvända händer transparent när du hämtar data. DATETIME-fält gör inte denna konvertering. De tar vad du än skickar dem och lagrar det bara direkt.

Varken fälttyperna DATETIME eller TIMESTAMP kan lagra data korrekt i en tidszon som observerar sommartid . Om du lagrar "2009-11-01 01:30:00" har fälten inget sätt att skilja vilken version av 01:30 du ville ha -- versionen -04:00 eller -05:00.

Ok, så vi måste lagra våra data i en icke-sommartid (som UTC). TIMESTAMP-fälten kan inte hantera denna data korrekt av skäl som jag ska förklara:om ditt system är inställt på en sommartidszon så kanske det du lägger in i TIMESTAMP inte är det du får tillbaka. Även om du skickar data till den som du redan har konverterat till UTC, kommer den fortfarande att anta att data finns i din lokala tidszon och göra ännu en konvertering till UTC. Denna TIMESTAMP-tilltvingade lokal-till-UTC-tillbaka-till-lokal tur-och returresa är förlust när din lokala tidszon observerar sommartid (sedan "2009-11-01 01:30:00" kartor till två olika möjliga tider).

Med DATETIME kan du lagra din data i vilken tidszon du vill och vara säker på att du kommer att få tillbaka vad du än skickar den (du tvingas inte in i de förlustfulla omvandlingar tur och retur som TIMESTAMP-fälten lägger på dig). Så lösningen är att använda ett DATETIME-fält och innan du sparar i fältet konvertera från din systemtidszon till vilken icke-DST-zon du vill spara den i (jag tror att UTC förmodligen är det bästa alternativet). Detta låter dig bygga in konverteringslogiken i ditt skriptspråk så att du explicit kan spara UTC-motsvarigheten till "2009-11-01 01:30:00 -04:00" eller ""2009-11-01 01:30:00 -05:00".

En annan viktig sak att notera är att MySQL:s matematiska funktioner för datum/tid inte fungerar korrekt runt sommargränser om du lagrar dina datum i en sommartid TZ. Så desto större anledning att spara i UTC.

I ett nötskal gör jag nu detta:

När data hämtas från databasen:

Tolka explicit data från databasen som UTC utanför MySQL för att få en korrekt Unix-tidsstämpel. Jag använder PHPs strtotime()-funktion eller dess DateTime-klass för detta. Det kan inte göras tillförlitligt inuti MySQL med MySQL:s CONVERT_TZ()- eller UNIX_TIMESTAMP()-funktioner eftersom CONVERT_TZ endast kommer att mata ut ett 'ÅÅÅÅ-MM-DD hh:mm:ss'-värde som lider av tvetydighetsproblem, och UNIX_TIMESTAMP() antar dess ingången är i systemets tidszon, inte den tidszon som data FAKTISKT lagrades i (UTC).

När data lagras i databasen:

Konvertera ditt datum till den exakta UTC-tid som du önskar utanför MySQL. Till exempel:med PHPs DateTime-klass kan du specificera "2009-11-01 1:30:00 EST" distinkt från "2009-11-01 1:30:00 EDT", sedan konvertera den till UTC och spara rätt UTC-tid till ditt DATETIME-fält.

Puh. Tack så mycket för allas input och hjälp. Förhoppningsvis sparar detta någon annan en del huvudvärk på vägen.

BTW, jag ser detta på MySQL 5.0.22 och 5.0.27



  1. Hur man kontrollerar om en beräknad kolumn är "beständig" i SQL Server

  2. Metoden org.postgresql.jdbc4.Jdbc4Connection.isValid(int) är ännu inte implementerad

  3. MySQL IN-operatörens prestanda på (stort?) antal värden

  4. Varför kraschade min MySQL-databas? Få insikter med den nya MySQL Freeze Frame