Cet article examine les principales différences entre le datetime2 et datetimeoffset types de données dans SQL Server.
Les deux types de données sont utilisés pour stocker les valeurs de date et d'heure. Les deux sont très similaires, mais avec une différence essentielle ; le datetimeoffset stocke le décalage horaire.
Cela entraîne également datetimeoffset utilisant plus d'espace de stockage que datetime2 , vous n'utiliserez donc que datetimeoffset si vous avez besoin du décalage horaire.
Voici un tableau qui décrit les principales différences entre ces deux types.
Fonctionnalité | datetimeoffset | datetime2 |
---|---|---|
Conformité SQL (ANSI et ISO 8601) | Oui | Oui |
Plage de dates | 0001-01-01 à 9999-12-31 | 0001-01-01 à 9999-12-31 |
Plage de temps | 00:00:00 à 23:59:59.9999999 | 00:00:00 à 23:59:59.9999999 |
Longueur des caractères | 26 postes minimum 34 maximum | 19 postes minimum 27 maximum |
Taille de stockage | 8 à 10 octets, selon la précision* * Plus 1 octet pour stocker la précision | 6 à 8 octets, selon la précision* * Plus 1 octet pour stocker la précision |
Précision | 100 nanosecondes | 100 nanosecondes |
Précision fractionnaire de seconde | Oui | Oui |
Précision fractionnaire de seconde définie par l'utilisateur | Oui | Oui |
Plage de décalage de fuseau horaire | -14h00 à +14h00 | Aucun |
Conscience et préservation du décalage horaire | Oui | Non |
Respect de l'heure d'été | Non | Non |
Dois-je utiliser "datetime2" ou "datetimeoffset" ?
Cela dépend si vous devez ou non inclure un décalage de fuseau horaire.
Si vous devez inclure un décalage de fuseau horaire, vous devrez utiliser datetimeoffset .
Sinon, utilisez datetime2 , car vous économiserez de l'espace de stockage et éliminerez tout problème potentiel lié à un décalage de fuseau horaire (potentiellement erroné) dans vos données.
Exemple 1 - Comparaison de base
Voici un exemple rapide pour démontrer la différence fondamentale entre datetime2 et datetimeoffset .
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';
Résultat :
+------------------------------------+-----------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-----------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.5555555 | +------------------------------------+-----------------------------+
Ici, j'ai mis un datetime2 variable à la même valeur que datetimeoffset variable. Cela entraîne la conversion de la valeur en datetime2 et nous pouvons alors utiliser un SELECT
instruction pour voir la valeur de chaque variable.
Les deux variables utilisent une échelle de 7, ce qui signifie qu'elles ont 7 décimales.
Donc, dans ce cas, la seule différence entre les deux est que le datetimeoffset la valeur inclut le décalage du fuseau horaire et la datetime2 la valeur ne le fait pas.
Exemple 2 - Modification de la précision
Les deux types vous permettent de spécifier une précision (en utilisant une échelle entre 0 et 7). Par conséquent, il est possible de définir la datetime2 valeur à une précision inférieure à datetimeoffset valeur (et inversement).
Exemple :
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';
Résultat :
+------------------------------------+-------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.556 | +------------------------------------+-------------------------+
Ici, je mets le datetime2 valeur sur une échelle de 3, ce qui signifie qu'elle se retrouve avec 3 décimales au lieu de 7. Dans ce cas, ses fractions de seconde sont arrondies (car le prochain chiffre fractionnaire est 5 ou plus).
Nous pouvons donc voir qu'il est possible d'obtenir une valeur de date/heure différente en fonction des fractions de secondes que nous attribuons à datetime2 . Cela fonctionne également dans l'autre sens (par exemple, si nous convertissons à partir de datetime2(7) à datetimeoffset(3) ).
Cependant, si nous réduisons la partie fractionnaire, aucun arrondi n'est effectué :
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';
Résultat :
+------------------------------------+-------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-------------------------| | 2025-05-21 10:15:30.5554444 +07:30 | 2025-05-21 10:15:30.555 | +------------------------------------+-------------------------+
Exemple 3 - Définition de valeurs à partir de littéraux de chaîne
Dans les exemples précédents, le datetime2 la valeur a été attribuée en la définissant sur la même valeur que datetimeoffset valeur. Lorsque nous faisons cela, SQL Server effectue une conversion implicite afin que les données « correspondent » au nouveau type de données.
Nous pouvons également attribuer la même valeur directement à la datetime2 variable (même si la documentation officielle n'indique pas explicitement qu'elle accepte un littéral de chaîne avec un décalage de fuseau horaire) :
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';
Résultat :
+------------------------------------+-----------------------------+ | datetimeoffset | datetime2 | |------------------------------------+-----------------------------| | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.5555555 | +------------------------------------+-----------------------------+
Exemple 4 - Taille de stockage
Le datetime2 le type de données utilise deux octets de stockage en moins que datetimeoffset pour une précision donnée.
Le datetime2 peut être de 6, 7 ou 8 octets, selon sa précision.
Le datetimeoffset peut être de 8, 9 ou 10 octets, selon sa précision.
Microsoft déclare que le datetime2 type utilise également 1 octet supplémentaire afin de stocker sa précision, auquel cas il utiliserait au moins 3 octets de plus que smalldatetime .
Cela s'applique également à datetimeoffset (même si ce n'est pas explicitement indiqué dans la documentation Microsoft).
Cependant, cela dépend si nous le stockons dans une table ou dans une variable, et si nous le convertissons ou non en une constante binaire.
Voici ce qui se passe si nous utilisons le DATALENGTH()
fonction pour retourner le nombre d'octets utilisés pour chacune de nos valeurs :
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';
Résultat
+------------------+-------------+ | datetimeoffset | datetime2 | |------------------+-------------| | 10 | 8 | +------------------+-------------+
Comme prévu, 10 octets pour datetimeoffset et 8 octets pour datetime2 .
Mais si nous les convertissons en varbinary , nous obtenons ceci :
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';
Résultat
+------------------+-------------+ | datetimeoffset | datetime2 | |------------------+-------------| | 11 | 9 | +------------------+-------------+
Un octet supplémentaire est ajouté à chaque valeur afin de stocker la précision.
De nombreux développeurs supposent que la conversion en varbinary est représentatif de la manière dont SQL Server stocke réellement les valeurs de date et d'heure. Cependant, ce n'est que partiellement vrai.
S'il est vrai que SQL Server stocke ses valeurs de date et d'heure au format hexadécimal, cette valeur hexadécimale n'inclut pas réellement la précision. En effet, la précision est incluse dans la définition de la colonne. Mais lorsque nous convertissons en varbinary comme nous l'avons fait dans l'exemple précédent, la précision est ajoutée, ce qui ajoute un octet supplémentaire.
Pour plus de détails sur la manière dont ces types de données sont stockés dans différents contextes, consultez les articles suivants :
- Comprendre la taille de stockage "datetimeoffset" dans SQL Server
- Comprendre la taille de stockage "datetime2" dans SQL Server