Armazenamento de DateTime (UTC) vs. armazenamento de DateTimeOffset


95

Normalmente tenho um "interceptor" que antes de ler / escrever de / para o banco de dados faz a conversão DateTime (de UTC para a hora local e da hora local para UTC), para que eu possa usar DateTime.Now(derivações e comparações) em todo o sistema sem me preocupar sobre fusos horários.

Em relação à serialização e movimentação de dados entre computadores, não há necessidade de se preocupar, pois a data e hora é sempre UTC.

Devo continuar armazenando minhas datas (SQL 2008 - datetime) no formato UTC ou, em vez disso, devo armazená-lo usando DateTimeOffset(SQL 2008 - datetimeoffset)?

As datas UTC no banco de dados (tipo datetime) estão funcionando e são conhecidas há tanto tempo, por que alterá-las? Quais são as vantagens?

Já li artigos como este , mas não estou 100% convencido. Alguma ideia?



1
Consulte também: DateTime vs DateTimeOffset - escrito para .Net, mas conceitualmente se aplica a SQL também.
Matt Johnson-Pint

Respostas:


131

Há uma grande diferença, onde você não pode usar o UTC sozinho.

  • Se você tem um cenário como este

    • Um servidor e vários clientes (todos geograficamente em diferentes fusos horários )
    • Os clientes criam alguns dados com informações de data e hora
    • Os clientes armazenam tudo no servidor central
  • Então:

    • datetimeoffset armazena o horário local do cliente e também o deslocamento para o horário UTC
    • todos os clientes sabem a hora UTC de todos os dados e também a hora local do local de origem das informações
  • Mas:

    • A data e hora UTC armazena apenas a data e hora UTC , então você não tem informações sobre a hora local no local do cliente onde os dados foram originados
    • Outros clientes não sabem a hora local do lugar de onde vieram as informações de data e hora
    • Outros clientes só podem calcular sua hora local a partir do banco de dados (usando a hora UTC) e não a hora local do cliente, de onde os dados foram originados

Um exemplo simples é o sistema de reserva de passagem aérea ... A passagem aérea deve conter 2 horários: - horário de "decolagem" (no fuso horário da cidade "De") - horário de "pouso" (no fuso horário da cidade "Destino")


2
Esta é a melhor explicação que li sobre quando seria apropriado, e tenho lido muito. Para nós, a partir disso, não me parece. Obtemos a hora em UTC para nossos dados externos e sabemos a localização de outra fonte, se necessário (e nunca foi). Obrigado por fazer isso parecer tão óbvio.
Andrew Backer

19
você disse "datetimeoffset armazena a hora UTC e TAMBÉM o deslocamento para a hora local do cliente", mas datetimeoffset armazena a hora LOCAL + deslocamento ou a hora UTC + deslocamento igual a +0.
Serhii Kyslyi

embora você possa apenas lançar o DTO para um DT, já que a base do DT é UTC (embora esta seja uma etapa extra para todos os que usam o banco de dados e, sem dúvida, não é mais simples do que usar apenas o horário UTC)
iliketocode

2
Parece mais como DateTmeOffset armazena "Hora local e deslocamento UTC", não "Hora UTC e deslocamento UTC". Se você lançar para data e hora ou usar qualquer uma das funções de parte de data, obterá os componentes de data e hora locais.
Triynko

" todos os clientes sabem a hora UTC de todos os dados e também a hora local do local de origem das informações" Embora armazenar como parte do campo de data pareça não normalizado nesse caso. Qual é o caso de uso - isto é, por que você não usaria UTC & pull out offset para InputLocationId(ou entidade normalizada semelhante). Haveria cálculos envolvidos (olá, exceções ... especialmente você, Indiana ), mas ainda é um processo determinístico - e então o equilíbrio da lógica de data e hora do aplicativo é direto.
ruffin

23

Você está absolutamente correto em usar o UTC para todos os tempos históricos (ou seja, eventos de registro ocorridos). Sempre é possível ir do UTC para a hora local, mas nem sempre o contrário.

Quando usar a hora local? Responda a esta pergunta:

Se o governo decidir repentinamente mudar o horário de verão, você gostaria que esses dados mudassem com ele?

Armazene a hora local apenas se a resposta for "sim". Obviamente, isso será apenas para datas futuras, e geralmente apenas para datas que afetem as pessoas de alguma forma.

Por que armazenar um fuso horário / deslocamento?

Em primeiro lugar, se você deseja registrar qual foi o deslocamento para o usuário que executou a ação, provavelmente seria melhor apenas fazer isso, ou seja, no login registre a localização e o fuso horário desse usuário.

Em segundo lugar, se você deseja converter para exibição, você precisa ter uma tabela de todas as transições de deslocamento de horário local para esse fuso horário, simplesmente saber o deslocamento atual não é suficiente, porque se você estiver mostrando uma data / hora de seis meses atrás, o deslocamento ser diferente.


4
A conversão do UTC do Windows em hora local leva em consideração quando o horário de verão muda para datas históricas. Não vejo por que você deseja armazenar a hora local nesse caso.
Jamiegs

1
@Jamiegs O Windows só conhece historicamente as "últimas informações históricas" (como é sugerido / observado na documentação do .NET DateTime). Não é abrangente.

2
claro, você também tem que armazenar o local do evento, caso contrário, você não pode dizer a que "hora local" o evento aconteceu.
keuleJ

20

Um DATETIMEOFFSET oferece a capacidade de armazenar a hora local e a hora UTC em um campo.

Isso permite relatórios muito simples e eficientes no horário local ou UTC, sem a necessidade de processar os dados para exibição de qualquer forma.

Esses são os dois requisitos mais comuns - hora local para relatórios locais e hora UTC para relatórios de grupo.

A hora local é armazenada na parte DATETIME de DATETIMEOFFSET e o OFFSET do UTC é armazenado na parte OFFSET, portanto a conversão é simples e, uma vez que não requer nenhum conhecimento do fuso horário de onde os dados vieram, pode ser feita no nível do banco de dados .

Se você não precisar de tempos menores que milissegundos, por exemplo, apenas minutos ou segundos, você pode usar DATETIMEOFFSET (0). O campo DATETIMEOFFSET exigirá apenas 8 bytes de armazenamento - o mesmo que DATETIME.

Usar DATETIMEOFFSET em vez de UTC DATETIME oferece mais flexibilidade, eficiência e simplicidade para relatórios.


Uma péssima estrutura de entidade não tem nenhum meio de acessar o datetime local de um campo datetimeoffset, tornando impossível consultar uma data local específica.
Triynko

@Triynko você pode explicar o que quer dizer? Exemplo?
reidLinden
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.