Este artigo destaca as principais diferenças entre o datetime 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. Mas há diferenças significativas entre os dois.
Talvez a diferença mais óbvia seja que o datetimeoffset armazena o deslocamento de fuso horário, enquanto datetime não.
Outra diferença importante é que datetimeoffset permite especificar a precisão (até 7 casas decimais). Isso significa que datetimeoffset os valores podem variar em seu tamanho de armazenamento, dependendo da precisão que está sendo usada.
O datahora Por outro lado, tem um tamanho de armazenamento fixo e precisão.
Geralmente, você deve evitar usar datetime a menos que você tenha um bom motivo para usá-lo (como dar suporte a um sistema legado). Além disso, o datetime2 tipo é uma correspondência mais próxima de datetimeoffset , então é melhor usar isso se não precisar de um deslocamento de fuso horário.
De qualquer forma, aqui está uma tabela que compara datetime e deslocamento de data e hora :
Recurso | deslocamento de data e hora | datahora |
---|---|---|
Compatível com SQL (ANSI e ISO 8601) | Sim | Não |
Período | 0001-01-01 a 9999-12-31 | 1753-01-01 a 9999-12-31 |
Intervalo de tempo | 00:00:00 até 23:59:59.9999999 | 00:00:00 até 23:59:59.997 |
Comprimento do caractere | mínimo de 26 posições máximo de 34 | mínimo de 19 posições máximo de 23 |
Tamanho do armazenamento | 8 a 10 bytes, dependendo da precisão* * Mais 1 byte para armazenar a precisão em alguns casos. Veja abaixo mais informações. | 8 bytes |
Precisão | 100 nanossegundos | Arredondado para incrementos de 0,000, 0,003 ou 0,007 segundos |
Precisão de segundo fracionário definida pelo usuário | Sim | Não |
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 |
Exemplo 1 – Comparação básica
De qualquer forma, aqui está um exemplo rápido para demonstrar a diferença básica entre datetime e deslocamento de data e hora .
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = @thedatetimeoffset; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime AS 'datetime';
Resultado:
+------------------------------------+-------------------------+ | datetimeoffset | datetime | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.557 | +------------------------------------+-------------------------+
Aqui, defino um datetime variável para o mesmo valor que o datetimeoffset variável. Isso faz com que o valor seja convertido em datetime e podemos então usar um
SELECT
para ver o valor de cada variável. Nesse caso, o deslocamento de data e hora O valor inclui o deslocamento do fuso horário e 7 casas decimais. O datahora value, por outro lado, não inclui o deslocamento de fuso horário e possui apenas 3 casas decimais. Além disso, seu terceiro dígito fracionário é arredondado para cima. Isso ocorre porque sua precisão é sempre arredondada para incrementos de 0,000, 0,003 ou 0,007 segundos.
Exemplo 2 – Definindo valores de literais de string
No exemplo anterior, o datetime 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.
Se tentarmos atribuir o mesmo valor diretamente ao datetime variável, obtemos um erro:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = '2025-05-21 10:15:30.5555555 +07:30'; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime AS 'datetime';
Resultado:
Msg 241, Level 16, State 1, Line 5 Conversion failed when converting date and/or time from character string.
Isso ocorre porque o datetime tipo de dados não oferece suporte a um literal de string com um deslocamento de fuso horário. Além disso, ele não suporta literais de string com mais de 3 casas decimais.
Portanto, se removermos o deslocamento de fuso horário, mas mantivermos todos os segundos fracionários, ainda receberemos um erro:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = '2025-05-21 10:15:30.5555555'; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime AS 'datetime';
Resultado:
Msg 241, Level 16, State 1, Line 5 Conversion failed when converting date and/or time from character string.
Para que funcione, precisaríamos atribuir um valor com no máximo 3 casas decimais:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = '2025-05-21 10:15:30.555'; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime AS 'datetime';
Resultado:
+------------------------------------+-------------------------+ | datetimeoffset | datetime | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.557 | +------------------------------------+-------------------------+
De qualquer forma, datetime sempre terá um valor diferente para datetimeoffset , porque não inclui o deslocamento do fuso horário. Isso será verdade mesmo se usarmos a mesma precisão de segundos fracionários e o mesmo valor de segundos fracionários.
Para demonstrar isso, veja o que acontece se atribuirmos o mesmo valor a datetimeoffset :
DECLARE @thedatetimeoffset datetimeoffset(3), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.123'; SET @thedatetime = '2025-05-21 10:15:30.123'; SELECT @thedatetimeoffset AS 'datetimeoffset', @thedatetime AS 'datetime';
Resultado:
+------------------------------------+-------------------------+ | datetimeoffset | datetime | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.1230000 +00:00 | 2025-05-21 10:15:30.123 | +------------------------------------+-------------------------+
Neste caso datetimeoffset usa uma escala de 3, que dá 3 casas decimais (o mesmo que datetime ). Isso é feito usando datetimeoffset(3) ao declarar a variável.
Também alterei os segundos fracionários para que datetime não os arredondaria (para que ambos os valores compartilhem exatamente a mesma parte fracionária).
Independentemente disso, deslocamento de data e hora ainda adiciona um deslocamento de fuso horário, definido para seu valor padrão de +00:00.
Observe que meu sistema exibe zeros à direita em datetimeoffset parte fracionária de, mas o valor usa apenas 3 casas decimais.
Exemplo 3 - Tamanho de armazenamento
O datahora tipo de dados usa 8 bytes.
O deslocamento de data e hora tipo de dados usa 8, 9 ou 10 bytes, dependendo de sua precisão.
Portanto, você não está salvando nenhum tamanho de armazenamento usando datetime .
No entanto, se você converter um offset de data e hora valor a uma constante binária, ele adiciona 1 byte para armazenar a precisão.
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), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = @thedatetimeoffset; SELECT DATALENGTH(@thedatetimeoffset) AS 'datetimeoffset', DATALENGTH(@thedatetime) AS 'datetime';
Resultado
+------------------+------------+ | datetimeoffset | datetime | |------------------+------------| | 10 | 8 | +------------------+------------+
Como esperado, 10 bytes para datetimeoffset e 8 bytes para datetime .
Mas se os convertermos em varbinary , obtemos o seguinte:
DECLARE @thedatetimeoffset datetimeoffset(7), @thedatetime datetime; SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30'; SET @thedatetime = @thedatetimeoffset; SELECT DATALENGTH(CAST(@thedatetimeoffset AS varbinary(16))) AS 'datetimeoffset', DATALENGTH(CAST(@thedatetime AS varbinary(16))) AS 'datetime';
Resultado
+------------------+------------+ | datetimeoffset | datetime | |------------------+------------| | 11 | 8 | +------------------+------------+
Um byte extra é adicionado ao datetimeoffset valor, mas não para o datetime valor. Isso ocorre porque o offset de data e hora value precisa de um byte extra para armazenar a precisão (porque a precisão é definida pelo usuário). O datahora value por outro lado tem uma precisão fixa, então não há necessidade de que a precisão seja armazenada com o valor.
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 não inclui a precisão ao armazenar datetimeoffset valores. Isso ocorre porque a precisão está incluída na definição da coluna.
Para obter mais detalhes sobre como esse tipo de dados é armazenado no banco de dados, consulte Noções básicas sobre o tamanho de armazenamento 'datetimeoffset' no SQL Server.
Devo usar 'datetime' ou 'datetimeoffset'?
Se você precisar incluir um deslocamento de fuso horário, precisará usar datetimeoffset . Caso contrário, datetime pode ser suficiente.
No entanto, a Microsoft recomenda que você use datetime2 para novos trabalhos, pois tem muitos benefícios em relação a datetime .
Consulte datetime vs datetime2 para obter uma comparação desses tipos de dados.