PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Ottieni l'ora con il fuso orario dall'ora senza fuso orario e il nome del fuso orario

ATTENZIONE:principiante di PostgreSQL (vedi commenti sulla domanda!). Tuttavia, conosco un po' i fusi orari, quindi so cosa ha senso chiedere.

Mi sembra che questa sia fondamentalmente una situazione non supportata (purtroppo) quando si tratta di AT TIME ZONE . Osservando AT TIME ZONE documentazione fornisce una tabella in cui i tipi di valore "input" sono solo:

  • Timestamp senza fuso orario
  • indicatore orario con fuso orario
  • ora con fuso orario

Ci manca quello che desideri:il tempo senza fuso orario. Quello che stai chiedendo è un po' logico, sebbene dipenda dalla data... poiché fusi orari diversi possono avere offset diversi a seconda della data. Ad esempio, 12:00:00 Europa/Londra maggio significa 12:00:00 UTC, oppure può significare 11:00:00 UTC, a seconda che sia inverno o estate.

Sul mio sistema, dopo aver impostato il fuso orario del sistema su America/Regina, la query

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

mi dà 2011-11-22 14:00:00-06 di conseguenza. Non è ideale , ma almeno fornisce il momento istantaneo (credo). Credo che se l'hai recuperato con una libreria client o lo hai confrontato con un altro TIMESTAMP WITH TIME ZONE - otterresti il ​​risultato giusto. È solo la conversione del testo che utilizza il sistema fuso orario per l'uscita.

Ti andrebbe bene? Puoi modificare il tuo SCHEDULES.time campo deve essere un TIMESTAMP WITHOUT TIME ZONE campo o (al momento della query) combinare l'ora dal campo con una data per creare un timestamp senza fuso orario?

EDIT:se sei soddisfatto della "data corrente", sembra come se potessi semplicemente cambiare la tua query in:

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

Naturalmente, l'attuale sistema la data potrebbe non essere la stessa della data corrente nel fuso orario locale . penso questo risolverà quella parte...

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

In altre parole:

  • Prendi l'istante corrente
  • Calcola la data/ora locale nel fuso orario dell'utente
  • Prendi la data
  • Aggiungi l'orario di pianificazione a quella data per ottenere un TIMESTAMP WITHOUT TIME ZONE
  • Usa AT TIME ZONE per applicare il fuso orario a quella data/ora locale

Sono sicuro che c'è un modo migliore, ma io penso ha senso.

Dovresti essere consapevole del fatto che in alcuni casi ciò potrebbe non riuscire:

  • Quale vuoi che sia il risultato per un'ora di 01:30 in un giorno in cui l'orologio salta dalle 01:00 alle 02:00, quindi 01:30 non si verifica affatto?
  • Quale vuoi che sia il risultato per un'ora di 01:30 in un giorno in cui l'orologio torna indietro dalle 02:00 all'01:00, quindi 01:30 si verifica due volte?