Almacenamiento de DateTime (UTC) frente a almacenamiento de DateTimeOffset

93

Por lo general, tengo un "interceptor" que, justo antes de leer / escribir desde / hacia la base de datos, realiza la conversión DateTime (de UTC a hora local y de hora local a UTC), por lo que puedo usar DateTime.Now(derivaciones y comparaciones) en todo el sistema sin preocuparme. sobre las zonas horarias.

Con respecto a la serialización y el movimiento de datos entre computadoras, no hay necesidad de preocuparse, ya que la fecha y hora siempre es UTC.

¿Debo seguir almacenando mis fechas (SQL 2008 - datetime) en formato UTC o debería almacenarlas usando DateTimeOffset(SQL 2008 - datetimeoffset)?

Las fechas UTC en la base de datos (tipo de fecha y hora) han estado funcionando y se conocen durante tanto tiempo, ¿por qué cambiarlas? ¿Cuáles son las ventajas?

Ya he mirado artículos como este , pero no estoy 100% convencido. ¿Alguna idea?

Frederico
fuente
Pregunta relacionada: stackoverflow.com/questions/2532729/…
Oded
1
Vea también: DateTime vs DateTimeOffset - escrito para .Net, pero conceptualmente se aplica también a SQL.
Matt Johnson-Pint

Respuestas:

131

Hay una gran diferencia, en la que no puede usar UTC solo.

  • Si tienes un escenario como este

    • Un servidor y varios clientes (todos geográficamente en diferentes zonas horarias )
    • Los clientes crean algunos datos con información de fecha y hora
    • Los clientes lo almacenan todo en el servidor central
  • Luego:

    • datetimeoffset almacena la hora local del cliente y TAMBIÉN la compensación a la hora UTC
    • todos los clientes conocen la hora UTC de todos los datos y también la hora local en el lugar donde se originó la información
  • Pero:

    • La fecha y hora UTC almacena solo la fecha y hora UTC , por lo que no tiene información sobre la hora local en la ubicación del cliente donde se originaron los datos
    • Otros clientes no conocen la hora local del lugar, de donde proviene la información de fecha y hora
    • Otros clientes solo pueden calcular su hora local a partir de la base de datos (usando la hora UTC), no la hora local del cliente, donde se originaron los datos.

Un ejemplo sencillo es el sistema de reserva de billetes de avión ... El billete de avión debe contener 2 horas: - hora de "despegue" (en la zona horaria de la ciudad "De") - hora de "aterrizaje" (en la zona horaria de la ciudad de "Destino")

Marcel Toth
fuente
2
Esta es la mejor explicación que he leído sobre cuándo sería apropiado, y he leído mucho Para nosotros, de esto, no parece que sea así. Obtenemos la hora en UTC para nuestros datos externos y conocemos la ubicación de otra fuente si es necesario (y nunca lo ha sido). Gracias por hacer que parezca tan obvio.
Andrew Backer
19
dijiste "datetimeoffset almacena la hora UTC y TAMBIÉN la compensación a la hora local del cliente", pero datetimeoffset almacena la hora LOCAL + Offset, o la hora UTC + offset igual a +0.
Serhii Kyslyi
aunque podría simplemente lanzar el DTO a un DT ya que la base de DT es UTC (aunque esto sería un paso adicional para todos los que usan la base de datos, y posiblemente no sea más simple que usar solo la hora UTC)
iliketocode
2
Parece más como que DateTmeOffset almacena "Hora local y compensación UTC", no "Hora UTC y compensación UTC". Si lanza a datetime o usa cualquiera de las funciones de datepart, obtiene los componentes de fecha y hora locales.
Triynko
" Todos los clientes conocen la hora UTC de todos los datos y también la hora local en el lugar donde se originó la información" Aunque, en ese caso, el almacenamiento como parte del campo de fecha no parece normalizado. ¿Cuál es el caso de uso? Es decir, ¿por qué no usarías UTC y sacarías el desplazamiento a InputLocationId(o una entidad normalizada similar)? Habría cálculos involucrados (hola, excepciones ... especialmente usted, Indiana ), pero sigue siendo un proceso determinista, y luego el equilibrio de la lógica de fecha y hora de la aplicación es sencillo.
ruffin
23

Tiene toda la razón al usar UTC para todos los tiempos históricos (es decir, se registraron eventos). Siempre es posible pasar de UTC a la hora local, pero no siempre al revés.

¿Cuándo usar la hora local? Responde esta pregunta:

Si el gobierno de repente decide cambiar el horario de verano, ¿le gustaría que estos datos cambiaran con él?

Solo guarde la hora local si la respuesta es "sí". Obviamente, eso solo será para fechas futuras, y generalmente solo para fechas que afectan a las personas de alguna manera.

¿Por qué almacenar una zona horaria / compensación?

En primer lugar, si desea registrar cuál fue el desplazamiento para el usuario que llevó a cabo la acción, probablemente sería mejor hacerlo, es decir, al iniciar sesión, registre la ubicación y la zona horaria de ese usuario.

En segundo lugar, si desea convertir para visualización, necesita tener una tabla de todas las transiciones de compensación de tiempo local para esa zona horaria, simplemente saber que la compensación actual no es suficiente, porque si está mostrando una fecha / hora de hace seis meses, la compensación será sé diferente.

Ben
fuente
4
La conversión de Windows UTC a la hora local tiene en cuenta cuándo cambia el horario de verano para las fechas históricas. No veo por qué querrías almacenar la hora local en ese caso.
Jamiegs
1
@Jamiegs Windows solo conoce históricamente la "última información histórica" ​​(como se insinúa / se indica en la documentación de .NET DateTime). No es exhaustivo.
2
por supuesto, también tienes que almacenar la ubicación del evento, de lo contrario no puedes decir a qué "hora local" ocurrió el evento.
keuleJ
20

Un DATETIMEOFFSET le brinda la posibilidad de almacenar la hora local y la hora UTC en un campo.

Esto permite generar informes muy simples y eficientes en hora local o UTC sin la necesidad de procesar los datos para su visualización de ninguna manera.

Estos son los dos requisitos más comunes: la hora local para los informes locales y la hora UTC para los informes de grupo.

La hora local se almacena en la parte DATETIME del DATETIMEOFFSET y el OFFSET de UTC se almacena en la parte OFFSET, por lo que la conversión es simple y, dado que no requiere conocimiento de la zona horaria de la que provienen los datos, todo se puede hacer a nivel de base de datos .

Si no necesita tiempos de milisegundos, por ejemplo, solo minutos o segundos, puede usar DATETIMEOFFSET (0). El campo DATETIMEOFFSET solo requerirá 8 bytes de almacenamiento, lo mismo que DATETIME.

Por lo tanto, el uso de DATETIMEOFFSET en lugar de UTC DATETIME brinda más flexibilidad, eficiencia y simplicidad para los informes.

Papillon Reino Unido
fuente
Lástima que el marco de la entidad no tenga forma alguna de acceder a la fecha y hora local de un campo datetimeoffset, lo que hace imposible la consulta de una fecha local en particular.
Triynko
@Triynko, ¿puedes explicar a qué te refieres? ¿Ejemplo?
reidLinden