Verificamos de forma profundamente cada secciones de nuestra página web con el objetivo de mostrarte siempre la información más veraz y actual.
Solución:
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 administración de pstgrsql TZ.
Expresar marcas de tiempo de PostgreSQL sin zonas en la hora local
Aquí es donde está pasando. Primero 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.m. PST (miércoles, 01 de enero de 2014 16:00:30 -0800) es equivalente al 2 de enero de 2014, 00:30 AM UTC (jueves, 02 de enero de 2014 00:00:30 + 0000). Cualquier momento después de las 4:00 pm en PST pasa al día siguiente, interpretado como UTC.
Además, como Erwin Brandstetter mencionó anteriormente, postresql tiene dos tipos de 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 es sin zona horaria, la ejecución del comando anterior no funcionará, y PRIMERO debe convertir su marca de tiempo sin zona horaria en una marca de tiempo con una zona horaria, es decir, una zona horaria UTC, y SÓLO ENTONCES convertirla a su deseado ‘PST’ o ‘US / Pacífico ‘(que son lo mismo hasta algunos problemas del horario de verano. Creo que debería estar bien con cualquiera de ellos).
Permítanme demostrar con un ejemplo en el que creo una marca de tiempo sin zona horaria. Supongamos por conveniencia que nuestra zona horaria local es de hecho ‘PST’ (si no lo fuera, 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 una UTC TZ, ¡pero postresql tiene sus propios planes!). En la práctica, lo que hace postgresql es que toma la marca de tiempo sin zona horaria (‘2014-01-2 00:30:00) y la trata como si YA FUERA una marca de tiempo’ PST ‘TZ (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.
No veo el exacto tipo de starts_at
en tu pregunta. Realmente debería incluir esta información, es la key a la solución. Tendré que adivinar.
Básicamente, PostgreSQL siempre almacena el valor de hora UTC para el tipo timestamp with time zone
internamente. Solo la pantalla varía con su timezone
configuración. El efecto de la AT TIME ZONE
La construcción también cambia con el tipo de datos subyacente. Más detalles:
- Ignorar las zonas horarias por completo en Rails y PostgreSQL
Si extrae un date
de tipo timestamp [without time zone]
, obtiene la fecha de la zona horaria actual. El día en la salida será el mismo que en la visualización del timestamp
valor.
Si extrae un date
de tipo timestamp with time zone
(timestamptz
para abreviar), el desplazamiento de zona horaria se “aplica” primero. Aún obtiene la fecha de la zona horaria actual, que coincide con la monitor de la marca de tiempo. El mismo punto en el tiempo se traduce al día siguiente en algunas partes de Europa, cuando son más de las 4 pm en California, por ejemplo. Para obtener la fecha de una determinada zona horaria, aplique AT TIME ZONE
primero.
Por lo tanto, lo que describe al principio de la pregunta contradice su ejemplo.
Dado que starts_at
es un timestamp [without time zone]
y la hora de su servidor se establece en la hora local. Prueba con:
SELECT now();
¿Muestra la misma hora que un reloj en tu pared? Si es así (y el servidor de base de datos se está ejecutando con la hora correcta), timezone
la configuración de su sesión actual coincide con su zona horaria local. Si la respuesta es no, es posible que desee visitar el entorno de timezone
en tus postgresql.conf
o su cliente para la sesión. Detalles en el manual.
Tenga en cuenta que el timezone
offset utilizó lo contrario firmar de lo que se muestra en los literales de marca de tiempo. Ver:
- Manejo peculiar de la zona horaria en una base de datos de Postgres
Para obtener su fecha local de starts_at
solo
SELECT starts_at::date
Tantamount a:
SELECT date(starts_at)
Por cierto, su hora local es 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 timestamp
valor) que UTC (zona horaria universal), pero durante los períodos de ahorro de luz diurna (como ahora) puede ser de 7 horas. Es por eso timestamptz
se muestra como 2012-06-21 02:00:00
-07
en tu ejemplo. El constructo AT TIME ZONE 'PST'
tiene en cuenta el horario de verano. Estas dos expresiones producen resultados diferentes (una en invierno, otra en verano) y pueden dar lugar a fechas diferentes cuando se emiten:
SELECT '2012-06-21 01:00:00'::timestamp AT TIME ZONE 'PST'
, '2012-12-21 01:00:00'::timestamp AT TIME ZONE 'PST'
Sé que este es antiguo, pero es posible que desees considerar el uso de AT TIME ZONE “EE. UU./Pacífico” al transmitir para evitar problemas de PST / PDT. Entonces
SELECT starts_at::TIMESTAMPTZ AT TIME ZONE "US/Pacific"
FROM schedules
WHERE ID = '40';
Si eres capaz, tienes la opción de dejar una noticia acerca de qué le añadirías a este post.