Nous avons affaire à une application qui doit gérer des données horaires globales provenant de différents fuseaux horaires et de paramètres d'heure d'été. L'idée est de tout stocker au format UTC en interne et de ne convertir que pour les interfaces utilisateur localisées. SQL Server offre-t-il des mécanismes permettant de gérer les traductions en fonction d'une heure, d'un pays et d'un fuseau horaire?
Cela doit être un problème commun, alors je suis surpris que Google ne trouve rien d’utilisable.
Des pointeurs?
7 ans ont passé et ...
En fait, cette nouvelle fonctionnalité de SQL Server 2016 répond exactement à vos besoins.
Il est appelé AT FUSEAU HORAIRE et il convertit la date en un fuseau horaire spécifié en tenant compte des changements de l'heure d'été (DST).
Plus d'infos ici: https://msdn.Microsoft.com/en-us/library/mt612795.aspx
Cela fonctionne pour les dates qui ont actuellement le même décalage UTC que l'hôte de SQL Server. il ne tient pas compte des changements de l'heure d'été. Remplacez YOUR_DATE
Par la date locale à convertir.
SELECT DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), YOUR_DATE);
Quelques-unes de ces réponses vous permettront de comprendre, mais vous ne pouvez pas faire ce que vous essayez de faire avec des dates arbitraires pour SqlServer 2005 et les versions antérieures en raison de l'heure avancée. L’utilisation de la différence entre l’UTC local et l’actuel UTC actuel me donnera le décalage tel qu’il existe aujourd’hui. Je n'ai pas trouvé le moyen de déterminer quelle compensation aurait été pour la date en question.
Cela dit, je sais que SqlServer 2008 fournit de nouvelles fonctions de date pouvant résoudre ce problème, mais les personnes utilisant une version antérieure doivent être conscientes des limitations.
Notre approche consiste à conserver le code UTC et à effectuer la conversion côté client, où nous contrôlons mieux la précision de la conversion.
SQL Server 2008 a un type appelé datetimeoffset
. C'est vraiment utile pour ce genre de choses.
http://msdn.Microsoft.com/en-us/library/bb630289.aspx
Vous pouvez ensuite utiliser la fonction SWITCHOFFSET
pour le déplacer d’un fuseau horaire à un autre, tout en conservant la même valeur UTC.
http://msdn.Microsoft.com/en-us/library/bb677244.aspx
Rob
Vous pouvez utiliser mon projet prise en charge du fuseau horaire SQL Server pour convertir les fuseaux horaires standard IANA, comme indiqué ici .
UTC to Local est comme ceci:
SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'America/Los_Angeles')
Local to UTC est comme ceci:
SELECT Tzdb.LocalToUtc('2015-07-01 00:00:00', 'America/Los_Angeles', 1, 1)
Les options numériques permettent de contrôler le comportement lorsque les valeurs de l’heure locale sont affectées par l’heure avancée. Celles-ci sont décrites en détail dans la documentation du projet.
Voici le code pour convertir une zone DateTime
en une autre zone DateTime
DECLARE @UTCDateTime DATETIME = GETUTCDATE();
DECLARE @ConvertedZoneDateTime DATETIME;
-- 'UTC' to 'India Standard Time' DATETIME
SET @ConvertedZoneDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time'
SELECT @UTCDateTime AS UTCDATE,@ConvertedZoneDateTime AS IndiaStandardTime
-- 'India Standard Time' to 'UTC' DATETIME
SET @UTCDateTime = @ConvertedZoneDateTime AT TIME ZONE 'India Standard Time' AT TIME ZONE 'UTC'
SELECT @ConvertedZoneDateTime AS IndiaStandardTime,@UTCDateTime AS UTCDATE
Remarque : AT TIME ZONE
ne fonctionne que sur SQL Server 2016 + et l'avantage est qu'il considère automatiquement la lumière du jour lors de la conversion en un fuseau horaire particulier
J'ai tendance à vouloir utiliser DateTimeOffset pour tout stockage date-heure qui n'est pas lié à un événement local (par exemple: réunion/fête, etc., de 12h à 15h au musée).
Pour obtenir le DTO actuel au format UTC:
DECLARE @utcNow DATETIMEOFFSET = CONVERT(DATETIMEOFFSET, SYSUTCDATETIME())
DECLARE @utcToday DATE = CONVERT(DATE, @utcNow);
DECLARE @utcTomorrow DATE = DATEADD(D, 1, @utcNow);
SELECT @utcToday [today]
,@utcTomorrow [tomorrow]
,@utcNow [utcNow]
REMARQUE: J'utiliserai toujours le temps UTC lors de l'envoi sur le réseau filaire ... Le JS côté client peut facilement se rendre au/à la heure UTC locale. Voir: new Date().toJSON()
...
Le JS suivant gérera l’analyse d’une date UTC/GMT au format ISO8601 en une heure locale.
if (typeof Date.fromISOString != 'function') {
//method to handle conversion from an ISO-8601 style string to a Date object
// Date.fromISOString("2009-07-03T16:09:45Z")
// Fri Jul 03 2009 09:09:45 GMT-0700
Date.fromISOString = function(input) {
var date = new Date(input); //EcmaScript5 includes ISO-8601 style parsing
if (!isNaN(date)) return date;
//early shorting of invalid input
if (typeof input !== "string" || input.length < 10 || input.length > 40) return null;
var iso8601Format = /^(\d{4})-(\d{2})-(\d{2})((([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d{1,12}))?)?)?)?)?([Zz]|([-+])(\d{2})\:?(\d{2}))?$/;
//normalize input
var input = input.toString().replace(/^\s+/,'').replace(/\s+$/,'');
if (!iso8601Format.test(input))
return null; //invalid format
var d = input.match(iso8601Format);
var offset = 0;
date = new Date(+d[1], +d[2]-1, +d[3], +d[7] || 0, +d[8] || 0, +d[10] || 0, Math.round(+("0." + (d[12] || 0)) * 1000));
//use specified offset
if (d[13] == 'Z') offset = 0-date.getTimezoneOffset();
else if (d[13]) offset = ((parseInt(d[15],10) * 60) + (parseInt(d[16],10)) * ((d[14] == '-') ? 1 : -1)) - date.getTimezoneOffset();
date.setTime(date.getTime() + (offset * 60000));
if (date.getTime() <= new Date(-62135571600000).getTime()) // CLR DateTime.MinValue
return null;
return date;
};
}
Oui, dans une certaine mesure comme détaillé ici .
L’approche que j’ai utilisée (avant 2008) consiste à effectuer la conversion dans la logique métier .NET avant de l’insérer dans la base de données.
Vous pouvez utiliser la fonction GETUTCDATE () pour obtenir la date et l'heure UTC. Vous pouvez probablement sélectionner la différence entre GETUTCDATE () et GETDATE () et utiliser cette différence pour ajuster vos dates à l'heure UTC.
Mais je suis d'accord avec le message précédent, il est beaucoup plus facile de contrôler le bon datetime dans la couche de gestion (dans .NET, par exemple).