Hay una respuesta larga y bastante esclarecedora sobre las diferencias entre
TIMESTAMP WITH TIME ZONE
-vs-TIMESTAMP WITHOUT TIME ZONE
disponible en esta publicación SO . Lo que me gustaría saber es: ¿hay algún caso de uso válido para usar realmente TIMESTAMP WITHOUT TIME ZONE
o debería considerarse un antipatrón?
postgresql
Marcus Junius Brutus
fuente
fuente
Respuestas:
Esto se afirma en muchos lugares, pero creo que vale la pena mencionar siempre cuando comparamos la
timestamp with time zone
contimestamp without time zone
tipos: eltimestamp WITH time zone
no almacena la zona horaria información junto con la marca de tiempo . Lo que hace es almacenar todos los datos en la zona horaria UTC, como se indica en los documentos :Se considera válido para algunos usar
timestamp WITHOUT time zone
en situaciones en las que (1) todo está en la misma zona horaria o (2) la capa de aplicación maneja la zona horaria y simplemente almacena todo en una determinada zona horaria (generalmente UTC). Pero también se considera un antipatrón, simple porque la solución correcta para (1) es configurar la configuración de TimeZone en la zona horaria dada para el sistema y (2) ya está resuelto, ya que PostgreSQL ya almacena todo en la misma zona horaria (UTC).Ahora, con esos dos caídos, puedo venir con solo una buena razón para usar
timestamp WITHOUT time zone
. Es entonces cuando desea almacenar eventos en el futuro y que se debe activar algún tipo de alerta cuando lleguemos a ese momento. Eso podría ser buenotimestamp WITH time zone
si, y solo si, las reglas definidas por las leyes de la región sobre la zona horaria nunca cambian. La regla más común que cambia es acerca de la adopción o no del horario de verano (DST).Por ejemplo, imagine que está en, digamos,
2013-06-15
(todavía no en horario de verano) programar algún evento para que ocurra2013-01-15 10:00
(que ya estaría en horario de verano), y en2013-06-15
su región fue designado para adoptar horario de verano; pero, algún tiempo después de eso, el gobierno cambió la regla y dijo que su región ya no usará DST, y de repente su hora programada se convierte2013-01-15 11:00
(en lugar de10:00
), que si usatimestamp WITH time zone
y mantiene sus configuraciones de TZ actualizadas. Por supuesto, también puede notar que es posible tratar tales casos también con la zona horaria, si realiza un seguimiento de los cambios de las reglas en las regiones / zonas horarias de su interés y actualiza los registros afectados.Vale la pena mencionar que algunas regiones a menudo cambian estas reglas (como en Brasil, algunos estados, no todo el país, a menudo cambian), pero en la mayoría de los casos lo cambia muy temprano, por lo que sus usuarios se verían afectados solo por eventos programados muy lejos de La hora actual.
Con todo lo dicho, solo tengo una sugerencia más. Si tiene usuarios, registros o cualquier cosa en diferentes zonas horarias, almacene la zona horaria de donde provienen y elija y use
timestamp with time zone
. De esa manera, puede (1) cruzar eventos que ocurren más cerca unos de otros para diferentes fuentes (independientemente de sus zonas horarias) y (2) mostrar la hora original (la hora del reloj) en que ocurrió el evento.fuente
Sí. Hay casos de uso para
TIMESTAMP WITHOUT TIME ZONE
.TIMESTAMP WITH TIME ZONE
, noWITHOUT
.TIMESTAMP WITHOUT TIME ZONE
los valores no son un punto en la línea de tiempo, no son momentos reales. Representan una idea aproximada sobre los posibles momentos, posibles puntos en la línea de tiempo a lo largo de un rango de aproximadamente 26-27 horas (el rango de zonas horarias de todo el mundo). No tienen un significado real hasta que aplique una zona horaria o un desplazamiento desde UTC .Ej: navidad
Por ejemplo, supongamos que necesita registrar el inicio de días festivos / días santos.
Para registrar el hecho de que la Navidad comienza después de la medianoche del 25 de diciembre de este año, tenemos que decir
2016-12-25 00:00:00
sin zona horaria. Temprano en los días de Papá Noel visita Auckland, Nueva Zelanda, justo después de la medianoche, ya que es una de las primeras noches en el mundo. Luego se dirige hacia el oeste, a medida que pasa la medianoche siguiente, y pronto llega a Filipinas. Luego, los renos se mueven en dirección oeste, llegando a la India a la medianoche, que ocurre varias horas después de la medianoche de Auckland. Mucho más tarde todavía es medianoche en París FR, y aún más tarde en Montreal CA. Todas estas visitas de Santa suceden en diferentes momentos, es tiempo , pero todas ocurrieron poco después de la medianoche, según la medianoche de cada localidad.Por lo tanto, grabar
2016-12-25 00:00:00
sin zona horaria al comienzo de la Navidad es informativo y legítimo, pero solo vagamente. Hasta que diga "Navidad en Auckland" o "Navidad en Montreal", no tenemos un momento específico en el tiempo. Si está grabando el momento real cada vez que el trineo aterrizó, usaría enTIMESTAMP WITH TIME ZONE
lugar delWITHOUT
tipo.Similar a la Navidad es la víspera de Año Nuevo. Cuando cae el Times Square Ball en Nueva York , la gente en Seattle todavía está enfriando su champán y preparando sus cuernos de fiesta . Sin embargo, registraríamos la idea del momento de Año Nuevo como
2017-01-01 00:00:00
en aTIMESTAMP WITHOUT TIME ZONE
. Por el contrario, si queremos registrar cuándo cayó la pelota en Nueva York, o cuando la gente en Seattle tocó sus cuernos, en su lugar usaríamosTIMESTAMP WITH TIME ZONE
(noWITHOUT
) para registrar esos momentos reales, cada tres horas separados el uno del otro.Ej: turnos de fábrica
Otro ejemplo podría ser registrar una política que implique la hora del reloj de pared en varias ubicaciones. Digamos que tenemos fábricas en Detroit, Düsseldorf y Delhi. Si decimos que en las tres fábricas el primer turno comienza a las 6 AM con un receso para el almuerzo a las 11:30 AM, eso podría registrarse como a
TIMESTAMP WITHOUT TIME ZONE
. Nuevamente, esta información es útil de una manera vaga, pero no indica un momento específico en el tiempo hasta que apliquemos una zona horaria. Un nuevo día amanece más temprano en el este. Entonces, la fábrica de Delhi será la primera en abrir a las 6 AM. Horas después, la fábrica de Düsseldorf comienza a funcionar a las 6 de la mañana. Pero la fábrica de Detroit en realidad no abrirá hasta otras seis horas más tarde, cuando sean las 6 AM.Contraste esta idea (de cuándo comienza generalmente el turno de fábrica) con el hecho histórico de cuándo hizo cada trabajador de fábrica para iniciar su turno en un día en particular. El reloj de entrada es un momento real, un punto real en la línea de tiempo. Entonces registraríamos eso en una columna de tipo en
TIMESTAMP WITH TIME ZONE
lugar delWITHOUT
tipo.Entonces, sí, hay casos de uso legítimos para
TIMESTAMP WITHOUT TIME ZONE
. Pero en mi experiencia con las aplicaciones comerciales, son relativamente raras. En los negocios, tendemos a preocuparnos por los momentos reales: cuándo llegó realmente la factura, cuándo entra en vigencia exactamente ese contrato, en qué momento se ejecutó esa transacción bancaria. Entonces, en situaciones tan comunes, queremos elTIMESTAMP WITH TIME ZONE
tipo.Para obtener más información, consulte mi Respuesta a la pregunta similar: ¿Debo almacenar marcas de tiempo UTC o tiempo local para turnos?
Postgres
Tenga en cuenta que Postgres específicamente nunca guarda la información de zona horaria especificada al insertar una marca de tiempo.
TIMESTAMP WITH TIME ZONE
TIMESTAMP WITH TIME ZONE
comoTIMESTAMP WITH RESPECT FOR TIME ZONE
.TIMESTAMP WITHOUT TIME ZONE
El estándar SQL apenas toca temas de comportamiento y tipos de datos de fecha y hora. Por lo tanto, la base de datos varía ampliamente en el manejo de fecha y hora.
fuente
21:00
)Me gustaría agregar otra vista a esto, que va en contra de gran parte de lo que se ha escrito en las otras respuestas. En mi opinión,
timestamp with time zone
tiene muy pocos casos de uso válidos ytimestamp without time zone
, en general, debería preferirse.Primero, debe comprender el patrón "UTC en todas partes", que generalmente se recomienda para todas las aplicaciones que no tienen requisitos muy especiales. Simplemente significa que su aplicación debe representar todas sus marcas de tiempo en UTC, en todas partes, todo el tiempo. Por supuesto, estará mostrando la fecha / hora local a los usuarios, pero la idea es convertirlos en el borde de su programa, al representar la vista. Este es el lugar correcto para combinar la marca de tiempo UTC (que puede haber cargado desde una base de datos) y la zona horaria del usuario (que puede haber venido del navegador) en una marca de tiempo local.
Si sigue este patrón, entonces
timestamp with time zone
es un antipatrón. Todo lo que hace este tipo es hacer que PostgreSQL realice conversiones de zona horaria al leer y escribir marcas de tiempo, según laTimeZone
variable de sesión de PostgreSQL . En lugar de tratar con zonas horarias en los bordes de su aplicación, las ha introducido en su corazón, en la comunicación con su base de datos. Debe tener cuidado de tener PostgreSQL siempreTimeZone
configurado correctamente en todo momento, agregando otro punto innecesario de falla y confusión.¿Y para qué? Si sigue el patrón UTC en todas partes, su aplicación solo tiene marcas de tiempo UTC de todos modos; Entonces, ¿por qué pedirle a su base de datos que haga conversiones de zona horaria en ellos? Simplemente puede almacenarlos en una
timestamp without time zone
columna y tratarlos como si siempre fueran UTC. Sin conversiones, sin zonas horarias, sin complicaciones.fuente
Instance
en NodaTime / JodaTime). Básicamente está describiendo una situación en la que casi se sigue "UTC en todas partes", o se sigue un poco ...timestamptz
. El objetivo de este tipo es realizar conversiones de zona horaria como valores leídos y escritos en PostgreSQL (internamente en la base de datos, la marca de tiempo siempre se guarda como UTC). Establecer siempre la zona horaria de la sesión en UTC deshabilita efectivamente esas conversiones, entonces, ¿por qué usarlastimestamptz
? Dicho de otra manera, si los valores en la base de datos son UTC, y los valores que entran y salen de la base de datos son siempre UTC, entonces ¿por qué tener conciencia de zona horaria en su base de datos?La
date
marca de tiempo tampoco incluye información de zona horaria, sin embargo, mucha gente la usa.Por supuesto, eso en sí mismo no es una respuesta.
Es válido para usar
timestamp
ydate
para cualquier marca de tiempo y fecha que siempre estén en la misma zona horaria, o que se almacenen en relación con alguna zona horaria conocida.Si la zona horaria es siempre la misma o implícita, entonces es más antipatrón almacenarla que no almacenarla (información redundante).
Las marcas de tiempo también se pueden utilizar para almacenar información técnica, como la utilizada en los registros de aplicaciones o para mediciones de rendimiento. En este caso, la zona horaria también puede no ser importante.
Por el contrario, si está diseñando o trabajando en un sistema distribuido o en cualquier sistema en el que partes del sistema se distribuirán en diferentes zonas horarias, podría considerarse un antipatrón para no usar
timestamp with timezone
, aunque algunos sistemas podrían estar diseñados para ejecutarse en una zona horaria, por ejemplo, UTC. En este caso, la lógica de la zona horaria puede estar siendo introducida en la capa de aplicación, pero lo consideraría un antipatrón, sí.fuente
timestamp without timezone
, pero ¿alguna vez me compra algo? De lo contrario, ¿por qué debería molestarme si eltimestamp with timezone data
tipo es siempre igual o más apropiado?timestamp without timezone
sería más rápida, pero eso probablemente solo sea importante si está procesando miles de millones de filas ...timestamp
ytimestamptz
ambos se almacenan de la misma manera. No hay información de zona horaria almacenada en atimestamptz
, sino que se convierte a UTC para almacenamiento. Yo diría que siempre se usatimestamptz
cuando las marcas de tiempo en cuestión denotan tiempo absoluto . Eso es todo lo quetimestamptz
significa. He escrito sobre esto aquí .Puede parecer tentador almacenar y procesar fechas / horas en hora local si su solicitud se limita a una sola zona horaria, pero creo que esto es un error.
Al volver del horario de verano a la hora estándar, se repite una hora en la hora local (suponiendo que la diferencia sea una hora). En el lugar donde vivo, esto suele suceder alrededor de las 2 a.m., por lo que la hora local corre 01:58, 01:59, 01:00 y solo avanza a las 02:00 al final de la hora repetida.
Si intenta ordenar eventos por hora utilizando la hora local, eso significa que los eventos de dos horas separadas se mezclan y no aparecen en el orden en que realmente ocurrieron.
En comparación, UTC no tiene este problema y hace un pedido limpio. Por lo tanto, incluso cuando trabaja con una sola zona horaria, desea que el DB almacene y procese las horas en UTC y las convierta a / desde la hora local para la entrada / visualización. Este es el comportamiento de TIMESTAMP WITH TIME ZONE.
fuente