sql >> Databasteknik >  >> RDS >> PostgreSQL

PostgreSQL date() med tidszon

Det du vill ha är i princip:

$ select starts_at AT TIME ZONE 'UTC' AT TIME ZONE 'US/Pacific' from schedules where id = 40

Jag fick lösningen från den här artikeln nedan, som är rakt GULD!!! Den förklarar denna icke-triviala fråga mycket tydligt, läs den om du vill förstå pstgrsql TZ-hantering bättre.

Uttrycker PostgreSQL-tidsstämplar utan zoner i lokal tid

Här är vad som pågår. Först bör du veta att 'PST-tidszonen är 8 timmar efter UTC-tidszonen, så till exempel 1 januari 2014, 16:30 PST (ons, 01 jan 2014 16:00:30 -0800) motsvarar 2 januari 2014, 00:30 AM UTC (tors 2 januari 2014 00:00:30 +0000). När som helst efter 16:00 i PST glider över till nästa dag, tolkat som UTC.

Dessutom, som Erwin Brandstetter nämnde ovan, har postresql två typer av tidsstämplar datatyper, en med en tidszon och en utan. Om dina tidsstämplar inkluderar en tidszon, då en enkel:

$ select starts_at AT TIME ZONE 'US/Pacific' from schedules where id = 40

kommer att funka. Men om din tidsstämpel är tidszonlös, kommer det inte att fungera att utföra kommandot ovan, och du måste FÖRST konvertera din tidszonlösa tidsstämpel till en tidsstämpel med en tidszon, nämligen en UTC-tidszon, och ENDAST DÅ konvertera den till önskad 'PST' eller 'US/ Pacific' (som är desamma upp till vissa sommartidsproblem. Jag tycker att du borde klara dig med båda).

Låt mig demonstrera med ett exempel där jag skapar en tidszonlös tidsstämpel. Låt oss för enkelhetens skull anta att vår lokala tidszon verkligen är 'PST' (om den inte vore det så blir det lite mer komplicerat vilket är onödigt för denna förklaring).

Säg att jag har:

$ select timestamp '2014-01-2 00:30:00' AS a, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AS b,  timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AT TIME ZONE 'PST' AS c, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d

Detta ger:

"a"=>"2014-01-02 00:30:00"   (This is the timezoneless timestamp)
"b"=>"2014-01-02 00:30:00+00" (This is the UTC TZ timestamp, note that up to a timezone, it is equivalent to the timezoneless one)
"c"=>"2014-01-01 16:30:00" (This is the correct 'PST' TZ conversion of the UTC timezone, if you read the documentation postgresql will not print the actual TZ for this conversion)
"d"=>"2014-01-02 08:30:00+00"

Den sista tidsstämpeln är anledningen till all förvirring när det gäller att konvertera tidszonlös tidsstämpel från UTC till 'PST' i postgresql. När vi skriver:

timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d

Vi tar en tidszonlös tidsstämpel och försöker konvertera den till 'PST TZ (vi antar indirekt att postgresql förstår att vi vill att den ska konvertera tidsstämpeln från en UTC TZ, men postresql har sina egna planer!). I praktiken, vad postgresql gör är att den tar den tidszonlösa tidsstämpeln ('2014-01-2 00:30:00) och behandlar den som om den REDAN VAR en 'PST' TZ-tidsstämpel (dvs:2014-01-2 00:30 :00 -0800) och konverterar det till UTC-tidszon!!! Så det skjuter den faktiskt 8 timmar framåt istället för bakåt! Således får vi (2014-01-02 08:30:00+00).

Hur som helst, detta sista (ointuitiva) beteende är orsaken till all förvirring. Läs artikeln om du vill ha en mer grundlig förklaring, jag fick faktiskt resultat som är lite annorlunda än deras på den sista delen, men den allmänna idén är densamma.



  1. ändra tabell byt namn på kolumn i Oracle-databasen

  2. Hur man ansluter till MySQL med PHP

  3. Har inte databaslås! i android

  4. SQLAlchemy, Psychopg2 och Postgresql COPY