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

Data di PostgreSQL() con fuso orario

Fondamentalmente quello che vuoi è:

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

Ho ottenuto la soluzione da questo articolo qui sotto, che è puro GOLD!!! Spiega molto chiaramente questo problema non banale, dai una lettura se desideri comprendere meglio la gestione di TZ di pstgrsql.

Esprimere timestamp PostgreSQL senza zone nell'ora locale

Ecco cosa sta succedendo. Per prima cosa dovresti sapere che "il fuso orario PST è 8 ore indietro rispetto al fuso orario UTC, quindi ad esempio 1 gennaio 2014, 16:30 PST (mercoledì 01 gennaio 2014 16:00:30 -0800) equivale a 2 gennaio 2014, 00:30 AM UTC (gio 02 gennaio 2014 00:00:30 +0000). In qualsiasi momento dopo le 16:00 in PST passa al giorno successivo, interpretato come UTC.

Inoltre, come menzionato sopra Erwin Brandstetter, postresql ha due tipi di dati di timestamp, uno con un fuso orario e uno senza. Se i tuoi timestamp includono un fuso orario, allora un semplice:

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

funzionerà. Tuttavia, se il tuo timestamp è senza fuso orario, l'esecuzione del comando sopra non funzionerà e devi PRIMA convertire il tuo timestamp senza fuso orario in un timestamp con un fuso orario, ovvero un fuso orario UTC, e SOLO QUINDI convertirlo nel tuo 'PST' o 'US/ Pacific' (che sono gli stessi fino ad alcuni problemi di ora legale. Penso che dovresti andare bene con entrambi).

Lasciami dimostrare con un esempio in cui creo un timestamp senza fuso orario. Assumiamo per comodità che il nostro fuso orario locale sia effettivamente "PST" (se non lo fosse, diventa un po' più complicato, il che non è necessario ai fini di questa spiegazione).

Supponiamo di avere:

$ 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

Questo produrrà:

"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"

L'ultimo timestamp è la ragione di tutta la confusione relativa alla conversione di timestamp senza fuso orario da UTC a "PST" in postgresql. Quando scriviamo:

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

Stiamo prendendo un timestamp senza fuso orario e proviamo a convertirlo in 'PST TZ (supponiamo indirettamente che postgresql capirà che vogliamo che converta il timestamp da un TZ UTC, ma postresql ha piani propri!). In pratica, ciò che fa Postgresql è prendere il timestamp timezoneless ('2014-01-2 00:30:00) e lo tratta come se FOSSE GIÀ un timestamp TZ 'PST' (es:2014-01-2 00:30 :00 -0800) e lo converte in fuso orario UTC!!! Quindi in realtà lo spinge 8 ore avanti invece che indietro! Così otteniamo (02-01-2014 08:30:00+00).

Comunque, quest'ultimo comportamento (non intuitivo) è la causa di tutta la confusione. Leggi l'articolo se vuoi una spiegazione più approfondita, in realtà ho ottenuto risultati un po' diversi dai loro su quest'ultima parte, ma l'idea generale è la stessa.