sql >> Databáze >  >> RDS >> PostgreSQL

Získejte čas s časovým pásmem z času bez časového pásma a názvu časového pásma

VAROVÁNÍ:Nováček v PostgreSQL (viz komentáře k otázce!). O časových pásmech však trochu vím, takže vím, co má smysl zeptat se.

Zdá se mi, že toto je v zásadě nepodporovaná situace (bohužel), pokud jde o AT TIME ZONE . Při pohledu na AT TIME ZONE dokumentaci poskytuje tabulku, kde jsou pouze typy "vstupních" hodnot:

  • časové razítko bez časového pásma
  • časové razítko s časovým pásmem
  • čas s časovým pásmem

Chybí nám ten, který chcete:čas bez časové pásmo. To, na co se ptáte, je poněkud logické, i když to závisí na datu... protože různá časová pásma mohou mít různé posuny v závislosti na datu. Například 12:00:00 Evropa/Londýn může znamená 12:00:00 UTC, nebo to může znamenat 11:00:00 UTC, v závislosti na tom, zda je zima nebo léto.

V mém systému, když jsem nastavil systémové časové pásmo na America/Regina, dotaz

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

dává mi 2011-11-22 14:00:00-06 jako výsledek. To není ideální , ale dává to alespoň okamžitý bod v čase (myslím). Domnívám se, že pokud jste to stáhli pomocí klientské knihovny – nebo ji porovnali s jinou TIMESTAMP WITH TIME ZONE - dostali byste správný výsledek. Je to jen převod textu, který pak používá systém časové pásmo pro výstup.

Stačilo by ti to? Můžete změnit svůj SCHEDULES.time pole být TIMESTAMP WITHOUT TIME ZONE pole, nebo (v době dotazu) zkombinovat čas z pole s datem a vytvořit tak časové razítko bez časového pásma?

EDIT:Pokud jste spokojeni s "aktuálním datem", vypadá jako můžete svůj dotaz změnit na:

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

Samozřejmě aktuální systém datum nemusí být stejné jako aktuální datum v místním časovém pásmu . Myslím tím se tato část opraví...

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

Jinými slovy:

  • Vezměte si aktuální okamžik
  • Zjistěte místní datum/čas v časovém pásmu uživatele
  • Vezměte si datum
  • Přidejte k tomuto datu plánovací čas, abyste získali TIMESTAMP WITHOUT TIME ZONE
  • Použijte AT TIME ZONE pro použití časového pásma na místní datum/čas

Jsem si jistý, že existuje lepší způsob, ale myslím to dává smysl.

Měli byste si být vědomi toho, že v některých případech to může selhat:

  • Jaký má být výsledek pro čas 01:30 v den, kdy hodiny přeskakují z 01:00 na 02:00, takže 01:30 vůbec nenastane?
  • Jaký má být výsledek pro čas 01:30 v den, kdy se hodiny vrátí z 02:00 na 01:00, takže 01:30 nastane dvakrát?


  1. Java Stored Procedure vs PL/SQL Stored Procedure

  2. Jak získat velikost tabulky v MySQL

  3. Přidejte nový sloupec do existující tabulky v MySql pomocí PHP s PDO

  4. Příkaz SQL CASE:Co to je a jaké jsou nejlepší způsoby jeho použití?