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

Obtener hora con zona horaria desde hora sin zona horaria y el nombre de la zona horaria

ADVERTENCIA:novato de PostgreSQL (¡vea los comentarios sobre la pregunta!). Sin embargo, sé un poco sobre las zonas horarias, así que sé lo que tiene sentido para preguntar.

Me parece que esta es básicamente una situación no admitida (desafortunadamente) cuando se trata de AT TIME ZONE . Mirando el EN LA ZONA HORARIA documentación proporciona una tabla donde los tipos de valores de "entrada" son solo:

  • marca de tiempo sin zona horaria
  • marca de tiempo con zona horaria
  • hora con zona horaria

Nos falta el que quieres:tiempo sin zona horaria. Lo que estás preguntando es algo lógico, aunque depende de la fecha... ya que diferentes zonas horarias pueden tener diferentes compensaciones dependiendo de la fecha. Por ejemplo, 12:00:00 Europa/Londres mayo significa 12:00:00 UTC, o puede significar 11:00:00 UTC, dependiendo de si es invierno o verano.

En mi sistema, habiendo establecido la zona horaria del sistema en America/Regina, la consulta

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

me da 2011-11-22 14:00:00-06 como resultado. Eso no es ideal , pero al menos da el punto instantáneo en el tiempo (creo). Creo que si obtuviste eso con una biblioteca de cliente, o lo comparaste con otro TIMESTAMP WITH TIME ZONE - Obtendrías el resultado correcto. Es solo la conversión de texto que luego usa el sistema zona horaria de salida.

¿Sería lo suficientemente bueno para ti? ¿Puedes cambiar tu SCHEDULES.time campo para ser un TIMESTAMP WITHOUT TIME ZONE o (en el momento de la consulta) combinar la hora del campo con una fecha para crear una marca de tiempo sin zona horaria?

EDITAR:si está satisfecho con la "fecha actual", parece como si pudiera cambiar su consulta a:

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

Por supuesto, el sistema actual la fecha puede no ser la misma que la fecha actual en la zona horaria local . yo creo esto arreglará esa 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

En otras palabras:

  • Toma el instante actual
  • Calcular la fecha/hora local en la zona horaria del usuario
  • Toma la fecha de eso
  • Agregue la hora programada a esa fecha para obtener un TIMESTAMP WITHOUT TIME ZONE
  • Usar AT TIME ZONE para aplicar la zona horaria a esa fecha/hora local

Estoy seguro de que hay una forma mejor, pero creo tiene sentido.

Sin embargo, debe tener en cuenta que, en algunos casos, esto podría fallar:

  • ¿Cuál desea que sea el resultado para una hora de la 01:30 en un día en el que el reloj salta de la 01:00 a las 02:00, de modo que la 01:30 no ocurra en absoluto?
  • ¿Cuál desea que sea el resultado para una hora de 01:30 en un día en que el reloj retrocede de 02:00 a 01:00, por lo que 01:30 ocurre dos veces?