PostgreSQL date () con zona horaria


Tengo un problema al seleccionar las fechas correctamente de Postgres - se están almacenando en UTC, pero no convertir con la función Date () correctamente.

Convertir la marca de tiempo a una fecha me da la fecha incorrecta si es más de 4pm PST.

2012-06-21 debe ser 2012-06-20 en este caso.

El tipo de datos de la columna starts_at es timestamp without time zone. Aquí están mis consultas:

Sin convertir a PST zona horaria:

Select starts_at from schedules where id = 40;

      starts_at      
---------------------
 2012-06-21 01:00:00

La conversión da esto:

Select (starts_at at time zone 'pst') from schedules where id = 40;
        timezone        
------------------------
 2012-06-21 02:00:00-07

Pero ni convertir a la fecha correcta en la zona horaria.

Author: Erwin Brandstetter, 2012-06-20

3 answers

No veo el exacto tipo de starts_at en tu pregunta. Usted realmente debe incluir esta información, es la clave de la solución. Tendré que adivinar.

Básicamente, PostgreSQL siempre almacena internamente el valor de tiempo UTC para el tipo timestamp with time zone. Solo la pantalla varía con la configuración actual de timezone. El efecto de la AT TIME ZONE construct también cambia con el tipo de datos subyacente. Más detalles:

Si extrae un date del tipo timestamp [without time zone], obtienes la fecha de la zona horaria actual. El día en la salida será el mismo que en la visualización del valor timestamp.

Si extrae un date del tipo timestamp with time zone (timestamptz para abreviar), el desplazamiento de la zona horaria se "aplica" primero. Todavía se obtiene la fecha de la zona horaria actual, que coincide con el mostrar de la marca de tiempo. El mismo punto en el tiempo se traduce en la al día siguiente en partes de Europa, cuando son más de las 4 p. m.en California, por ejemplo. Para obtener la fecha de una zona horaria determinada, primero aplique AT TIME ZONE.

Por lo tanto, lo que usted describe en la parte superior de la pregunta contradice su ejemplo.

Dado que starts_at es un timestamp [without time zone] y la hora en su servidor se establece en la hora local. Prueba con:

SELECT now();

¿Se muestra al mismo tiempo que un reloj en su pared? En caso afirmativo (y el servidor db se está ejecutando con la hora correcta), el timezone la configuración de su sesión actual concuerda con su zona horaria local. Si no, es posible que desee visitar la configuración de timezone en su postgresql.conf o su cliente para la sesión. Detalles en el manual.

Tenga en cuenta que el desplazamiento timezoneutiliza el signo opuesto de lo que se muestra en literales de marca de tiempo. Véase:

Para obtener su fecha local de starts_at solo

SELECT starts_at::date

Equivalente a:

SELECT date(starts_at)

POR cierto, su hora local está en UTC-7 en este momento, no UTC-8, porque el horario de verano está en vigor (no entre las ideas más brillantes de la raza humana).

La HORA Estándar del Pacífico (PST) es normalmente 8 horas "antes" (mayor valor timestamp) que UTC (Zona Horaria Universal), pero durante los períodos de verano (como ahora) puede ser de 7 horas. Es por eso que timestamptz se muestra como 2012-06-21 02:00:00-07 en su ejemplo. La construcción AT TIME ZONE 'PST' toma el horario de verano en cuenta. Estas dos expresiones producen resultados diferentes (una en invierno, otra en verano) y pueden resultar en diferentes fechas cuando se lanzan:

SELECT '2012-06-21 01:00:00'::timestamp AT TIME ZONE 'PST'
     , '2012-12-21 01:00:00'::timestamp AT TIME ZONE 'PST'
 24
Author: Erwin Brandstetter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-17 11:02:05

Básicamente lo que quieres es:

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

Tengo la solución de este artículo está a continuación, que es ORO recto!!! Explica muy claramente este tema no trivial, léalo si desea comprender mejor la administración de pstgrsql TZ.

Expresar las marcas de tiempo de PostgreSQL sin zonas en la hora local

Esto es lo que está pasando. En primer lugar usted debe saber que 'zona horaria PST es 8 horas detrás de la zona horaria UTC así que por ejemplo Jan 1st 2014, 4: 30 PM PST (Mié, 01 Ene 2014 16: 00:30 -0800) es equivalente a Jan 2nd 2014, 00: 30 AM UTC (Jue, 02 Jan 2014 00:00:30 +0000). En cualquier momento después de las 4:00 pm en PST se desliza al día siguiente, interpretado como UTC.

También, como Erwin Brandstetter mencionó anteriormente, postresql tiene dos tipos de tipo de datos de marcas de tiempo, uno con una zona horaria y otro sin. 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

Funcionará. 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, a saber, una zona horaria UTC, y SOLO ENTONCES convertirlo a su deseado 'PST' o 'EE.UU./Pacífico' (que son los mismos hasta algunos problemas de horario de verano. Creo que usted debe estar bien con cualquiera).

Permítanme demostrar con un ejemplo donde creo una marca de tiempo sin zona horaria. Supongamos por conveniencia que nuestra zona horaria local es de hecho ' PST ' (si no lo fuera, entonces se vuelve un poco más complicado, lo que es innecesario a los efectos de esta explicación).

Digamos 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 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 (suponemos indirectamente que postgresql entenderá que queremos convertir la marca de tiempo de una TZ UTC, pero postresql tiene planes propios!). En la práctica, lo que hace postgresql es que toma la marca de tiempo sin hora ('2014-01-2 00:30:00) y lo trata como si YA fuera una marca de tiempo TZ' PST ' (es decir: 2014-01-2 00:30:00 -0800) y convierte eso a la zona horaria UTC!!! ¡Así que en realidad lo empuja 8 horas por delante en lugar de hacia atrás! Así obtenemos (2014-01-02 08:30:00+00).

De todos modos, este último comportamiento (no intuitivo) es la causa de toda confusión. Leer el artículo si quieres una explicación más completa, en realidad tengo resultados que son un poco diferente entonces su en esta última parte, pero la idea general es la misma.

 23
Author: AmitF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-08 06:05:19

Sé que este es un viejo pero es posible que desee considerar el uso en LA ZONA HORARIA "US/Pacific" al emitir para evitar cualquier problema PST/PDT. So

SELECCIONE starts_at:: TIMESTAMPTZ EN LA ZONA HORARIA "US / Pacific" DE horarios DONDE ID = '40';

 7
Author: John Rennpferd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-04 16:43:33