sql >> Database teknologi >  >> RDS >> Mysql

MySQL datetime-felter og sommertid -- hvordan refererer jeg til den ekstra time?

Jeg har fundet ud af det til mit formål. Jeg vil opsummere, hvad jeg har lært (beklager, disse noter er ordrette; de ​​er lige så meget for min fremtidige henvisning som noget andet).

I modsætning til hvad jeg sagde i en af ​​mine tidligere kommentarer, gør felterne DATETIME og TIMESTAMP opføre sig anderledes. TIMESTAMP-felter (som dokumenterne angiver) tager hvad end du sender dem i "ÅÅÅÅ-MM-DD tt:mm:ss"-format og konverterer det fra din nuværende tidszone til UTC-tid. Det omvendte sker gennemsigtigt, hver gang du henter dataene. DATETIME-felter foretager ikke denne konvertering. De tager hvad end du sender dem og gemmer det bare direkte.

Hverken felttyperne DATETIME eller TIMESTAMP kan gemme data nøjagtigt i en tidszone, der overholder sommertid . Hvis du gemmer "2009-11-01 01:30:00", har felterne ingen måde at skelne mellem, hvilken version af 1:30 du ønskede -- versionen -04:00 eller -05:00.

Ok, så vi skal gemme vores data i en ikke-sommertidszone (såsom UTC). TIMESTAMP-felter er ikke i stand til at håndtere disse data nøjagtigt af grunde, som jeg vil forklare:Hvis dit system er indstillet til en DST-tidszone, er det, du sætter i TIMESTAMP, muligvis ikke det, du får ud igen. Selvom du sender den data, som du allerede har konverteret til UTC, vil den stadig antage, at dataene er i din lokale tidszone og foretage endnu en konvertering til UTC. Denne TIMESTAMP-håndhævede lokal-til-UTC-tilbage-til-lokal rundrejse er tabsgivende, når din lokale tidszone overholder sommertid (siden "2009-11-01 01:30:00" korter til 2 forskellige mulige tidspunkter).

Med DATETIME kan du gemme dine data i enhver tidszone, du ønsker, og være sikker på, at du vil få tilbage, hvad end du sender dem (du bliver ikke tvunget ind i de tabsgivende rundrejsekonverteringer, som TIMESTAMP-felter pålægger dig). Så løsningen er at bruge et DATETIME-felt og før du gemmer i feltet konverter fra din systemtidszone til den ikke-DST-zone, du vil gemme den i (jeg tror, ​​at UTC nok er den bedste mulighed). Dette giver dig mulighed for at indbygge konverteringslogikken i dit scriptsprog, så du eksplicit kan gemme UTC-ækvivalenten til "2009-11-01 01:30:00 -04:00" eller ""2009-11-01 01:30:00 -05:00".

En anden vigtig ting at bemærke er, at MySQL's matematiske funktioner for dato/klokkeslæt ikke fungerer korrekt omkring sommertid grænser, hvis du gemmer dine datoer i en DST TZ. Så desto mere grund til at spare i UTC.

I en nøddeskal gør jeg nu dette:

Når du henter data fra databasen:

Fortolk eksplicit dataene fra databasen som UTC uden for MySQL for at få et nøjagtigt Unix-tidsstempel. Jeg bruger PHPs strtotime()-funktion eller dens DateTime-klasse til dette. Det kan ikke udføres pålideligt inde i MySQL ved hjælp af MySQL's CONVERT_TZ()- eller UNIX_TIMESTAMP()-funktioner, fordi CONVERT_TZ kun udsender en 'ÅÅÅÅ-MM-DD tt:mm:ss'-værdi, som lider af tvetydighedsproblemer, og UNIX_TIMESTAMP() antager sin input er i systemets tidszone, ikke den tidszone dataene FAKTISK blev gemt i (UTC).

Når data gemmes i databasen:

Konverter din dato til den præcise UTC-tid, som du ønsker uden for MySQL. For eksempel:med PHP's DateTime-klasse kan du angive "2009-11-01 1:30:00 EST" adskilt fra "2009-11-01 1:30:00 EDT", derefter konvertere den til UTC og gemme den korrekte UTC-tid til dit DATETIME-felt.

Pyha. Mange tak for alles input og hjælp. Forhåbentlig sparer dette en anden for hovedpine hen ad vejen.

BTW, jeg ser dette på MySQL 5.0.22 og 5.0.27



  1. MySQL-fejl:nøglespecifikation uden nøglelængde

  2. Sådan fungerer Asinh() i PostgreSQL

  3. Pivotering af data ved hjælp af to kolonner

  4. Sådan filtreres rækker med null-værdier i Select Statement i SQL Server - SQL Server / TSQL Tutorial Del 110