web-dev-qa-db-fra.com

Conversion de date et heure du fuseau horaire en fuseau horaire dans le serveur SQL

J'ai une colonne d'horodatage UNIX dans ma table de base de données, qui provient d'un système situé dans le fuseau horaire du Koweït.

Le fuseau horaire de mon serveur de base de données est Eastern Time US & Canada. Maintenant, je dois convertir l'horodatage UNIX en valeur de date de fuseau horaire du Koweït à l'aide d'une requête SQL.

Quelqu'un peut-il me dire comment convertir cet horodatage UNIX en valeur de date de fuseau horaire au Koweït?

14
Ashish Rathore

Les horodatages Unix sont des nombres entiers de secondes depuis le 1er janvier 1970 UTC.

En supposant que vous voulez dire que vous avez une colonne entière dans votre base de données avec ce numéro, le fuseau horaire de votre serveur de base de données n'est pas pertinent.

Convertissez d'abord l'horodatage en type datetime:

SELECT DATEADD(second, yourTimeStamp, '1970-01-01')

Ce sera l'UTC datetime qui correspond à votre horodatage.

Ensuite, vous devez savoir comment ajuster cette valeur à votre fuseau horaire cible. Dans une grande partie du monde, une seule zone peut avoir plusieurs décalages, en raison de l'heure d'été.

Malheureusement, SQL Server n'a pas la possibilité de travailler directement les fuseaux horaires de travail. Ainsi, si vous utilisiez, par exemple, l'heure du Pacifique américain, vous n'auriez aucun moyen de savoir si vous devez soustraire 7 heures ou 8 heures. D'autres bases de données (Oracle, Postgres, MySql, etc.) ont des moyens intégrés pour gérer cela, mais hélas, SQL Server ne le fait pas. Donc, si vous recherchez une solution à usage général, vous devrez effectuer l'une des opérations suivantes:

  • Importez des données de fuseau horaire dans une table et conservez cette table à mesure que les règles de fuseau horaire changent. Utilisez ce tableau avec un tas de logique personnalisée pour résoudre le décalage pour une date particulière.

  • Utilisation xp_regread pour obtenir les clés de registre Windows qui contiennent des données de fuseau horaire et utiliser à nouveau un tas de logique personnalisée pour résoudre le décalage pour une date particulière. Bien sûr, xp_regread est une mauvaise chose à faire, nécessite certaines autorisations accordées et n'est pas pris en charge ou document.

  • Écrivez une fonction SQLCLR qui utilise la classe TimeZoneInfo dans .Net. Malheureusement, ceci nécessite un assemblage SQLCLR "dangereux" , et peut provoquer de mauvaises choses.

À mon humble avis, aucune de ces approches n'est très bonne, et il n'y a pas de bonne solution pour le faire directement en SQL. La meilleure solution serait de renvoyer la valeur UTC (soit l'entier d'origine, soit le datetime à UTC) à votre code d'application appelant, et de faire la conversion de fuseau horaire à la place (avec, par exemple, TimeZoneInfo dans .Net ou des mécanismes similaires sur d'autres plates-formes).

CEPENDANT - vous avez eu de la chance en ce que le Koweït est (et a toujours été) dans une zone qui ne change pas pour l'heure d'été. Il a toujours été UTC + 03: 00. Vous pouvez donc simplement ajouter trois heures et renvoyer le résultat:

SELECT DATEADD(hour, 3, DATEADD(second, yourTimeStamp, '1970-01-01'))

Mais reconnaissez que ce n'est pas une solution à usage général qui fonctionnera dans n'importe quel fuseau horaire.

Si vous le souhaitez, vous pouvez renvoyer l'un des autres types de données SQL, tels que datetimeoffset, mais cela ne vous aidera qu'à refléter que la valeur est décalée de trois heures par rapport à quiconque pourrait la consulter. Cela ne rendra pas le processus de conversion différent ou meilleur.


Réponse mise à jour

J'ai créé un projet pour prendre en charge les fuseaux horaires dans SQL Server. Vous pouvez l'installer d'ici . Ensuite, vous pouvez simplement convertir comme ceci:

SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'Asia/Kuwait')

Vous pouvez utiliser n'importe quel fuseau horaire de la base de données IANA tz , y compris ceux qui utilisent l'heure d'été.

Vous pouvez toujours utiliser la méthode que j'ai montrée ci-dessus pour convertir à partir d'un horodatage Unix. Les mettre ensemble:

SELECT Tzdb.UtcToLocal(DATEADD(second, yourTimeStamp, '1970-01-01'), 'Asia/Kuwait')

Mis à jour à nouveau

Avec SQL Server 2016, il existe désormais une prise en charge intégrée des fuseaux horaires avec le AT TIME ZONE instruction. Ceci est également disponible dans Azure SQL Database (v12).

SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time'

Plus d'exemples dans cette annonce.

27