sql >> Base de Datos >  >> RDS >> PostgreSQL

Fecha de PostgreSQL () con zona horaria

Básicamente lo que quieres es:

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

¡Obtuve la solución de este artículo a continuación, que es directamente ORO! Explica muy claramente este problema no trivial, léalo si desea comprender mejor la gestión de pstgrsql TZ.

Expresar marcas de tiempo de PostgreSQL sin zonas en hora local

Aquí es donde está pasando. En primer lugar, debe saber que la zona horaria PST está 8 horas por detrás de la zona horaria UTC, por lo que, por ejemplo, el 1 de enero de 2014 a las 4:30 p. AM UTC (jueves, 02 de enero de 2014 00:00:30 +0000). Cualquier momento después de las 4:00 p. m. en PST pasa al día siguiente, interpretado como UTC.

Además, como Erwin Brandstetter mencionó anteriormente, postresql tiene dos tipos de datos de marcas de tiempo, uno con una zona horaria y otro sin ella. Si sus marcas de tiempo incluyen una zona horaria, entonces un simple:

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

trabajará. Sin embargo, si su marca de tiempo no tiene zona horaria, ejecutar el comando anterior no funcionará, y PRIMERO debe convertir su marca de tiempo sin zona horaria a una marca de tiempo con una zona horaria, es decir, una zona horaria UTC, y SOLAMENTE ENTONCES convertirla a su 'PST' o 'US/ Pacific' (que son lo mismo excepto por algunos problemas con el horario de verano. Creo que debería estar bien con cualquiera de los dos).

Permítanme demostrar con un ejemplo donde creo una marca de tiempo sin zona horaria. Asumamos por conveniencia que nuestra zona horaria local es de hecho 'PST' (si no fuera así, se vuelve un poco más complicado, lo cual es innecesario para el propósito de esta explicación).

Di que tengo:

$ 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

Esto producirá:

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

La última marca de tiempo es la razón de toda la confusión con respecto a la conversión de la marca de tiempo sin zona horaria de UTC a 'PST' en postgresql. Cuando escribimos:

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

Estamos tomando una marca de tiempo sin zona horaria e intentamos convertirla a 'PST TZ (asumimos indirectamente que postgresql entenderá que queremos que convierta la marca de tiempo de UTC TZ, ¡pero postresql tiene sus propios planes!). En la práctica, lo que hace postgresql es tomar la marca de tiempo sin zona horaria ('2014-01-2 00:30:00) y la trata como si YA FUERA una marca de tiempo TZ 'PST' (es decir:2014-01-2 00:30 :00 -0800) y lo convierte a la zona horaria UTC!!! ¡Así que en realidad lo adelanta 8 horas en lugar de retroceder! Así obtenemos (2014-01-02 08:30:00+00).

De todos modos, este último comportamiento (poco intuitivo) es la causa de toda confusión. Lea el artículo si desea una explicación más completa, en realidad obtuve resultados que son un poco diferentes a los de esta última parte, pero la idea general es la misma.