web-dev-qa-db-fra.com

SQL Server 2008 - Comment convertir une date/heure GMT (UTC) en date/heure locale?

J'ai un proc d'insertion qui passe dans GETDATE() comme une des valeurs parce que chaque insert stocke également quand il a été inséré. Ceci est hébergé sur SQL Azure - qui utilise GMT.

Maintenant, lorsque je reçois des messages, la date GMT est stockée pour chacun d'eux dans leurs colonnes d'horodatage. Comment puis-je la convertir en datetime locale pour l'endroit où vous vous trouvez lorsque vous accédez à ma page?

Merci.

10
slandau

Vous pouvez faire quelque chose comme ça:

declare @InputUtcDateTime datetime2 = '2011-05-20 06:30:18'

declare @LocalDateTime datetime2 = dateadd(minute, datepart(TZoffset, sysdatetimeoffset()), @InputUtcDateTime)
print @LocalDateTime

ou

declare @InputUtcDateTime datetime2 = '2011-05-20 06:30:18'

declare @LocalDateTime datetime2 = dateadd(minute, datediff(minute, sysutcdatetime(), sysdatetime()), @InputUtcDateTime)
print @LocalDateTime
10
Alex Aza

Outre le problème de l'heure d'été, pourquoi ne pas simplifier avec:

yourDateTime - getutcdate() + getdate()
5
bwperrin

Pour MST par exemple ... considérant que chaque DTM est déjà stocké dans GMT, cela simplifie les choses.

SWITCHOFFSET(CONVERT(DATETIMEOFFSET, [ColumnName]), '-07:00')

Maintenant, si votre date/heure locale est autre chose que GMT/UTC, vous voudrez probablement utiliser ce qui suit ...

SWITCHOFFSET(TODATETIMEOFFSET([ColumnName], datepart(tz,sysdatetimeoffset())),'+00:00')

Voici la ventilation.

  • SWITCHOFFSET - convertit une valeur DateTimeOffset en un fuseau horaire différent, tout en préservant le décalage.
  • TODATETIMEOFFSET - convertit une valeur DateTime en une valeur DateTimeOffset à un fuseau horaire spécifié.
  • DATEPART - dans ce cas, obtient le fuseau horaire de la date/heure locale.
  • '+00:00' - le décalage cible, dans le deuxième exemple, est la cible UTC/GMT, de local ... le premier exemple concerne MST.

NOTE/AVERTISSEMENT: Je ne crois pas que cela représente une heure avancée, ce qui pourrait être un problème pour vous. Si la conservation absolue n'est pas nécessaire, vous pouvez simplement ajouter une colonne secondaire, avec la conversion approximative, et avancer en toute sécurité.

Vous voudrez peut-être faire abstraction de la logique dans un appel de fonction, afin de prendre en compte la préservation de l'heure d'été ... Cela ne devrait toutefois pas être trop difficile à faire.

1
Tracker1

Voici une fonction qui fonctionne sur les données historiques. Je l'ai écrit pour l'heure d'été britannique - qui se produit malheureusement le dernier dimanche des mois de mars et octobre, ce qui rend la logique un peu compliquée.

Fondamentalement, la partie de date codée en dur 01/03 recherche le dernier dimanche de mars et le 01/10, le dernier dimanche d’octobre (date à laquelle les horloges vont et viennent ici). REMARQUE: SI VOTRE SERVEUR IS UTILISANT LES DATES INDIVIDUELLES AMÉRICAINES INVERSE CES DEUX PARTIES DE DATE AUX 03/01 ET 10/01 !!!!

Donc, vous le transmettez à une date UTC et il sera automatiquement déterminé si une date historique est BST ou GMT. Ce n'est pas la meilleure chose à utiliser sur un ensemble de données volumineuses, mais c'est une solution.

Exécutez ce script pour créer la fonction et appelez-la en ligne dans votre sélection. SQL 2008 a un problème avec les fonctions définies par l'utilisateur, semble-t-il, il met une ligne rouge sous le code, mais il l'exécute aussi longtemps que vous utilisez le préfixe dbo (SELECT dbo.UTCConvert (votre date) pour l'exécuter)

CREATE FUNCTION [dbo].[UTCConvert] 
(

    @p1 datetime
)
RETURNS datetime
AS
BEGIN

    DECLARE @Result datetime


RETURN CASE 
WHEN
@p1 >
(DATEADD(day,DATEDIFF(day,'19000107',DATEADD(month,DATEDIFF(MONTH,0,'01/03/' + CAST(DATEPART(year,@p1) as CHAR)),30))/7*7,'19000107'))
AND
@p1<
(DATEADD(day,DATEDIFF(day,'19000107',DATEADD(month,DATEDIFF(MONTH,0,'01/10/' + CAST(DATEPART(year,@p1) as CHAR)),30))/7*7,'19000107'))
THEN (DATEADD(HH, 1, @p1)) 
ELSE @p1
END
END
0
Rich