Solución:
Esto se afirma en muchos lugares, pero creo que vale la pena mencionarlo siempre cuando comparamos las timestamp with time zone
con timestamp without time zone
tipos: los timestamp WITH time zone
no almacena el 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:
Para la marca de tiempo con zona horaria, el valor almacenado internamente está siempre en UTC (hora universal coordinada, tradicionalmente conocida como hora media de Greenwich, GMT). Un valor de entrada que tiene una zona horaria explícita especificada se convierte a UTC utilizando el desplazamiento apropiado para esa zona horaria. Si no se indica una zona horaria en la entrada string, entonces se supone que está en la zona horaria indicada por el parámetro TimeZone del sistema y se convierte a UTC utilizando el desplazamiento de la zona horaria.
Se considera válido para que algunos lo utilicen 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 anti-patrón, simple porque la solución correcta para (1) es configurar la configuración de TimeZone a 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 abajo, puedo venir con solo una buena razón para usar timestamp WITHOUT time zone
. Es entonces cuando desea almacenar eventos en el futuro y debe activarse algún tipo de alerta cuando lleguemos a ese momento. Eso podría ser bueno para timestamp WITH time zone
si, y solo si, las reglas definidas por las leyes de la región sobre la zona horaria no cambiaran nunca. La regla más común que cambia es sobre la adopción o no del horario de verano (DST).
Por ejemplo, imagina que estás en, digamos, 2013-06-15
(aún no en horario de verano) programe algún evento para que ocurra en 2013-01-15 10:00
(que ya estaría en horario de verano), y en 2013-06-15
su región fue designada para adoptar DST; pero, algún tiempo después de eso, el gobierno cambió la regla y dijo que su región ya no usará el horario de verano, y de repente su hora programada se convierte en 2013-01-15 11:00
(en lugar de 10:00
), que si usas timestamp WITH time zone
y mantenga sus configuraciones de TZ actualizadas. Por supuesto, también puede notar que es posible tratar estos casos también con la zona horaria, si realiza un seguimiento de los cambios de 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, cambian a menudo), pero en la mayoría de los casos lo cambian mucho antes, 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 la que provienen y elija y use timestamp with time zone
. De esa manera, puede (1) cruzar eventos que suceden más cerca entre sí para diferentes fuentes (independientemente de sus zonas horarias) y (2) mostrar la hora original (la hora del reloj) en que ocurrió el evento.
Si. Hay casos de uso para TIMESTAMP WITHOUT TIME ZONE
.
- En aplicaciones comerciales comunes, este tipo solo se usaría para:
- Reserva de citas futuras
- Representar la misma hora del día en varias zonas horarias, como el mediodía del día 23 en Tokio y en París (dos momentos diferentes con horas de diferencia, la misma hora del día)
- Para rastrear momentos, puntos específicos en la línea de tiempo, use siempre
TIMESTAMP WITH TIME ZONE
, noWITHOUT
.
TIMESTAMP WITHOUT TIME ZONE
los valores son no un punto en la línea de tiempo, no momentos reales. Representan una idea aproximada sobre potencial 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 alrededor del mundo). No tienen un significado real hasta que aplica una zona horaria o un desplazamiento de UTC.
Ej: Navidad
Por ejemplo, digamos que necesita registrar el inicio de las vacaciones / días festivos.
Table: holiday_
Column: year_ Type: SMALLINT
Column: description_ Type: VARCHAR
Column: start_ Type: TIMESTAMP WITHOUT TIME ZONE
Para registrar el hecho de que la Navidad comienza después de la medianoche del 25 de diciembre de este año, debemos decir 2016-12-25 00:00:00
sin ninguna zona horaria. Temprano en el día de Papá Noel visita Auckland NZ poco después de la medianoche, ya que es una de las primeras medianoche del mundo. Luego se abre camino hacia el oeste, cuando llega la siguiente medianoche, y pronto llega a Filipinas. Luego, los renos se mueven en dirección oeste y llegan a la India a la medianoche, lo que ocurre varias horas después de la medianoche de Auckland. Mucho más tarde aún es la medianoche en París FR, y aún más tarde la medianoche en Montreal CA. Todas estas visitas de Santa ocurren en diferentes momentos es tiempo, sin embargo, todo sucedió poco después de la medianoche, según la medianoche de cada localidad.
Entonces grabando 2016-12-25 00:00:00
sin ningún huso horario ya que el 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. Si está grabando el momento real cada vez que el trineo toca tierra, usaría TIMESTAMP WITH TIME ZONE
en lugar del WITHOUT
escribe.
Similar a la Navidad es la víspera de Año Nuevo. Cuando llega el Times Square Ball en Nueva York, la gente de Seattle todavía está enfriando su champán y preparando sus cuernos de fiesta. Sin embargo, registraríamos el idea del momento de Año Nuevo como 2017-01-01 00:00:00
en un TIMESTAMP WITHOUT TIME ZONE
. Por el contrario, si queremos registrar cuándo cayó la pelota en Nueva York, o cuándo la gente de Seattle hizo sonar sus cuernos, en su lugar usaríamos TIMESTAMP WITH TIME ZONE
(no WITHOUT
) para registrar esos momentos reales, cada uno con tres horas de diferencia.
Ej: turnos de fábrica
Otro ejemplo podría ser el registro de una política que implique el tiempo de 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 a. M. Con una pausa para el almuerzo a las 11:30 a. M., Eso podría registrarse como un TIMESTAMP WITHOUT TIME ZONE
. Nuevamente, esta información es útil de manera vaga pero no indica un momento específico en el tiempo hasta que aplicamos una zona horaria. Un nuevo día amanece más temprano en el este. Así que la fábrica de Delhi será la primera en abrir a las 6 de la mañana. Horas más tarde, la fábrica de Düsseldorf comienza a funcionar a las 6 de la mañana. Pero la fábrica de Detroit no abrirá realmente hasta otras seis horas más tarde, cuando sucedan las 6 de la mañana.
Compare esta idea (de cuándo generalmente comienza el turno de fábrica) con el hecho histórico de cuándo cada trabajador de la fábrica ficha para comenzar 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 TIMESTAMP WITH TIME ZONE
en lugar del WITHOUT
escribe.
Entonces, sí, existen casos de uso legítimos para TIMESTAMP WITHOUT TIME ZONE
. Pero en mi experiencia con las aplicaciones empresariales, son relativamente raras. En los negocios, tendemos a preocuparnos por los momentos reales: cuándo llegó realmente la factura, cuándo exactamente entra en vigencia ese contrato, en qué momento se ejecutó esa transacción bancaria. Entonces, en situaciones tan comunes, queremos TIMESTAMP WITH TIME ZONE
escribe.
Para obtener más información, consulte mi Respuesta a la pregunta similar, ¿Debo almacenar las marcas de tiempo UTC o la hora local para los turnos?
Postgres
Tenga en cuenta que Postgres específicamente Nunca guarda la información de la zona horaria especificada al insertar una marca de tiempo.
TIMESTAMP WITH TIME ZONE
- Cualquier zona horaria especificada o desplazamiento incluido con los datos de entrada se usa para ajustar el valor a UTC y se almacena. La información de zona / compensación pasada se descarta. Pensar en
TIMESTAMP WITH TIME ZONE
comoTIMESTAMP WITH RESPECT FOR TIME ZONE
. - Una entrada de 12:00 del mediodía del 7 de marzo de este año en India tendrá su hora del día ajustada a UTC restando cinco horas y media: 6:30 a.m.
- Cualquier zona horaria especificada o desplazamiento incluido con los datos de entrada se usa para ajustar el valor a UTC y se almacena. La información de zona / compensación pasada se descarta. Pensar en
TIMESTAMP WITHOUT TIME ZONE
- Cualquier zona horaria especificada o desplazamiento incluido con los datos de entrada se ignora por completo.
- Una entrada de 12:00 del mediodía del 7 de marzo de este año en India se registra como 12:00 del 7 de marzo de este año sin ajuste.
El estándar SQL apenas toca cuestiones de comportamiento y tipos de datos de fecha y hora. Entonces la base de datos varía ampliamente en el manejo de fecha-hora.
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, y timestamp without time zone
debería preferirse en general.
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, mostrará la fecha / hora local a los usuarios, pero la idea es convertirlas en el borde mismo de su programa, al renderizar la vista. Este es el lugar adecuado para combinar la marca de tiempo UTC (que puede haber cargado desde una base de datos) y la zona horaria del usuario (que puede provenir del navegador) en una marca de tiempo local.
Si sigue este patrón, entonces timestamp with time zone
es un anti-patró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 su PostgreSQL TimeZone
variable de sesión. En lugar de tratar con zonas horarias en los límites de su aplicación, las ha introducido en su corazón, en la comunicación con su base de datos. Debes tener cuidado de tener siempre PostgreSQL TimeZone
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 un timestamp without time zone
columna y trátelo como si siempre fuera UTC. Sin conversiones, sin zonas horarias, sin complicaciones.
Tienes la opción de añadir valor a nuestro contenido tributando tu experiencia en las crónicas.