sql >> Databasteknik >  >> RDS >> PostgreSQL

Få tid med tidszon från tid utan tidszon och tidszonens namn

VARNING:PostgreSQL-nybörjare (se kommentarer på frågan!). Jag kan dock lite om tidszoner, så jag vet vad som är vettigt att fråga.

Det verkar för mig som att detta i princip är en situation som inte stöds (tyvärr) när det gäller AT TIME ZONE . Tittar på VID TIDZON dokumentation det ger en tabell där "input" värdetyperna endast är:

  • tidsstämpel utan tidszon
  • tidsstämpel med tidszon
  • tid med tidszon

Vi saknar den du vill ha:tid utan tidszon. Det du frågar är något logiskt, även om det beror på datum... eftersom olika tidszoner kan ha olika förskjutningar beroende på datum. Till exempel, 12:00:00 Europa/London maj betyder 12:00:00 UTC, eller det kan betyda 11:00:00 UTC, beroende på om det är vinter eller sommar.

På mitt system, efter att ha ställt in systemets tidszon till America/Regina, kommer frågan

SELECT ('2011-11-22T12:00:00'::TIMESTAMP WITHOUT TIME ZONE) 
                               AT TIME ZONE 'America/Vancouver'

ger mig 2011-11-22 14:00:00-06 som ett resultat. Det är inte idealiskt , men det ger åtminstone den ögonblickliga tidpunkten (tror jag). Jag tror att om du hämtade det med ett klientbibliotek - eller jämförde det med en annan TIMESTAMP WITH TIME ZONE - du skulle få rätt resultat. Det är bara textkonverteringen som sedan använder systemet tidszon för utgång.

Skulle det vara tillräckligt bra för dig? Kan du antingen ändra din SCHEDULES.time fältet ska vara en TIMESTAMP WITHOUT TIME ZONE eller (vid frågetillfället) kombinera tiden från fältet med ett datum för att skapa en tidsstämpel utan tidszon?

EDIT:Om du är nöjd med det "aktuella datumet" ser det ut som att du bara kan ändra din fråga till:

SELECT (current_date + SCHEDULES.time) AT TIME ZONE USERS.tz
from SCHEDULES JOIN USERS on USERS.ID=SCHEDULES.USERID

Naturligtvis det nuvarande systemet datum kanske inte är detsamma som det aktuella datumet i den lokala tidszonen . Jag tror detta kommer att fixa den delen...

SELECT ((current_timestamp AT TIME ZONE USERS.tz)::DATE + schedules.time)
       AT TIME ZONE USERS.tz
from SCHEDULES JOIN USERS on USERS.ID=SCHEDULES.USERID

Med andra ord:

  • Ta det aktuella ögonblicket
  • Arbeta ut lokalt datum/tid i användarens tidszon
  • Ta datumet för det
  • Lägg till schemaläggningstiden till det datumet för att få en TIMESTAMP WITHOUT TIME ZONE
  • Använd AT TIME ZONE för att tillämpa tidszonen på det lokala datumet/tiden

Jag är säker på att det finns ett bättre sätt, men jag tror det är vettigt.

Du bör vara medveten om att detta i vissa fall kan misslyckas dock:

  • Vad vill du att resultatet ska bli för en tid på 01:30 en dag då klockan hoppar från 01:00 till 02:00, så att 01:30 inte inträffar alls?
  • Vad vill du att resultatet ska bli för en tid på 01:30 en dag då klockan går tillbaka från 02:00 till 01:00, så 01:30 inträffar två gånger?


  1. Ta bort sql-rader där ID:n inte har en matchning från en annan tabell

  2. Hur man tar bort en mysql-post med jquery

  3. synkronisera fjärrdatabas (mysql) med SQLite-databas och vice versa

  4. Hur väljer man 1d array från 2d array?