Este artigo analisa as principais diferenças entre o datetime2 e deslocamento de data e hora tipos de dados no SQL Server.
Ambos os tipos de dados são usados para armazenar valores de data e hora. Ambos são muito semelhantes, mas com uma diferença fundamental; o deslocamento de data e hora armazena o deslocamento de fuso horário.
Isso também resulta em datetimeoffset usando mais espaço de armazenamento do que datetime2 , então você só usaria datetimeoffset se você precisar do deslocamento de fuso horário.
Aqui está uma tabela que descreve as principais diferenças entre esses dois tipos.
Recurso | deslocamento de data e hora | datahora2 |
---|---|---|
Compatível com SQL (ANSI e ISO 8601) | Sim | Sim |
Período | 0001-01-01 a 9999-12-31 | 0001-01-01 a 9999-12-31 |
Intervalo de tempo | 00:00:00 até 23:59:59.9999999 | 00:00:00 até 23:59:59.9999999 |
Comprimento do caractere | mínimo de 26 posições máximo de 34 | 19 posições no mínimo 27 no máximo |
Tamanho do armazenamento | 8 a 10 bytes, dependendo da precisão* * Mais 1 byte para armazenar a precisão | 6 a 8 bytes, dependendo da precisão* * Mais 1 byte para armazenar a precisão |
Precisão | 100 nanossegundos | 100 nanossegundos |
Precisão de segundo fracionário | Sim | Sim |
Precisão de segundo fracionário definida pelo usuário | Sim | Sim |
Intervalo de deslocamento de fuso horário | -14:00 até +14:00 | Nenhum |
Reconhecimento e preservação de deslocamento de fuso horário | Sim | Não |
Conhece o horário de verão | Não | Não |
Devo usar 'datetime2' ou 'datetimeoffset'?
Isso depende se você precisa ou não incluir um deslocamento de fuso horário.
Se você precisar incluir um deslocamento de fuso horário, precisará usar datetimeoffset .
Caso contrário, use datetime2 , pois você economizará espaço de armazenamento e eliminará possíveis problemas com um deslocamento de fuso horário (potencialmente errado) em seus dados.
Exemplo 1 – Comparação básica
Aqui está um exemplo rápido para demonstrar a diferença básica entre datetime2 e deslocamento de data e hora .
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(7); SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime2 = @thedatetimeoffset; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime2 AS 'datetime2';
Resultado:
+------------------------------------+-----------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-----------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.5555555 | +------------------------------------+-----------------------------+
Aqui, defino um datetime2 variável para o mesmo valor que o datetimeoffset variável. Isso faz com que o valor seja convertido em datetime2 e podemos então usar um
SELECT
para ver o valor de cada variável. Ambas as variáveis usam uma escala de 7, o que significa que elas têm 7 casas decimais.
Portanto, neste caso, a única diferença entre os dois é que o datetimeoffset o valor inclui o deslocamento do fuso horário e o datetime2 valor não.
Exemplo 2 – Alteração da precisão
Ambos os tipos permitem especificar uma precisão (usando uma escala entre 0 e 7). Portanto, é possível definir o datetime2 valor para uma precisão menor do que o datetimeoffset valor (e vice-versa).
Exemplo:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(3); SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime2 = @thedatetimeoffset; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime2 AS 'datetime2';
Resultado:
+------------------------------------+-------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.556 | +------------------------------------+-------------------------+
Aqui eu defino o datetime2 valor para uma escala de 3, o que significa que termina com 3 casas decimais em vez de 7. Nesse caso, seus segundos fracionários são arredondados para cima (porque o próximo dígito fracionário é 5 ou superior).
Assim, podemos ver que é possível obter um valor de data/hora diferente dependendo dos segundos fracionários que atribuímos a datetime2 . Isso também funciona no sentido inverso (por exemplo, se convertermos de datetime2(7) para datetimeoffset(3) ).
No entanto, se reduzirmos a parte fracionária, nenhum arredondamento é realizado:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(3); SET @thedatetimeoffset = '2025-05-21 10:15:30.5554444 +07:30'; SET @thedatetime2 = @thedatetimeoffset; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime2 AS 'datetime2';
Resultado:
+------------------------------------+-------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.5554444 +07:30 | 2025-05-21 10:15:30.555 | +------------------------------------+-------------------------+
Exemplo 3 – Definindo valores de literais de string
Nos exemplos anteriores, o datetime2 valor foi atribuído definindo-o com o mesmo valor que o datetimeoffset valor. Quando fazemos isso, o SQL Server realiza uma conversão implícita para que os dados “se ajustem” ao novo tipo de dados.
Também podemos atribuir o mesmo valor diretamente ao datetime2 variável (mesmo que a documentação oficial não declare explicitamente que aceita uma string literal com um deslocamento de fuso horário):
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(7); SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime2 = '2025-05-21 10:15:30.5555555 +07:30'; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime2 AS 'datetime2';
Resultado:
+------------------------------------+-----------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-----------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.5555555 | +------------------------------------+-----------------------------+
Exemplo 4 – Tamanho de armazenamento
O datetime2 tipo de dados usa dois bytes a menos de armazenamento do que datetimeoffset para qualquer precisão.
O datetime2 pode ser de 6, 7 ou 8 bytes, dependendo de sua precisão.
O deslocamento de data e hora pode ser de 8, 9 ou 10 bytes, dependendo de sua precisão.
A Microsoft afirma que o datetime2 type também usa 1 byte extra para armazenar sua precisão, caso em que usaria pelo menos 3 bytes a mais que smalldatetime .
Isso também se aplica a datetimeoffset (mesmo que não seja explicitamente declarado na documentação da Microsoft).
No entanto, isso depende se estamos armazenando em uma tabela ou em uma variável e se estamos convertendo ou não em uma constante binária.
Aqui está o que acontece se usarmos o
DATALENGTH()
função para retornar o número de bytes usados para cada um dos nossos valores:DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(7); SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime2 = @thedatetimeoffset; SELECT DATALENGTH(@thedatetimeoffset) AS 'datetimeoffset', DATALENGTH(@thedatetime2) AS 'datetime2';
Resultado
+------------------+-------------+ | datetimeoffset | datetime2 | |------------------+-------------| | 10 | 8 | +------------------+-------------+
Como esperado, 10 bytes para datetimeoffset e 8 bytes para datetime2 .
Mas se os convertermos em varbinary , obtemos o seguinte:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime2 datetime2(7); SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime2 = @thedatetimeoffset; SELECT DATALENGTH(CAST(@thedatetimeoffset AS varbinary(16))) AS 'datetimeoffset', DATALENGTH(CAST(@thedatetime2 AS varbinary(16))) AS 'datetime2';
Resultado
+------------------+-------------+ | datetimeoffset | datetime2 | |------------------+-------------| | 11 | 9 | +------------------+-------------+
Um byte extra é adicionado a cada valor para armazenar a precisão.
Muitos desenvolvedores supõem que a conversão para varbinary é representativo de como o SQL Server realmente armazena valores de data e hora. No entanto, isso é apenas parcialmente verdade.
Embora seja verdade que o SQL Server armazena seus valores de data e hora em hexadecimal, esse valor hexadecimal na verdade não inclui a precisão. Isso ocorre porque a precisão está incluída na definição da coluna. Mas quando convertemos para varbinary como fizemos no exemplo anterior, a precisão é prefixada e isso adiciona um byte extra.
Para obter mais detalhes sobre como esses tipos de dados são armazenados em diferentes contextos, consulte os seguintes artigos:
- Compreendendo o tamanho do armazenamento de 'datetimeoffset' no SQL Server
- Compreendendo o tamanho do armazenamento 'datetime2' no SQL Server