Wir haben es mit einer Anwendung zu tun, die globale Zeitdaten aus verschiedenen Zeitzonen und Sommerzeiteinstellungen verarbeiten muss. Die Idee ist, alles intern im UTC-Format zu speichern und nur für die lokalisierten Benutzeroberflächen hin und her zu konvertieren. Bietet der SQL Server Mechanismen für den Umgang mit den Übersetzungen in einer bestimmten Zeit, einem bestimmten Land und einer bestimmten Zeitzone?
Dies muss ein häufiges Problem sein, daher bin ich überrascht, dass Google nichts Nutzbares auftauchen lässt.
Irgendwelche Hinweise?
sql-server
tsql
sql-server-2008
timezone
utc
BuschnicK
quelle
quelle
Antworten:
7 Jahre vergingen und ...
tatsächlich gibt es diese neue SQL Server 2016-Funktion, die genau das tut, was Sie brauchen.
Es heißt AT TIME ZONE und konvertiert das Datum unter Berücksichtigung der Änderungen der Sommerzeit in eine bestimmte Zeitzone.
Weitere Informationen finden Sie hier: https://msdn.microsoft.com/en-us/library/mt612795.aspx
quelle
Dies funktioniert für Daten, die derzeit denselben UTC-Offset wie der Host von SQL Server haben. Änderungen der Sommerzeit werden nicht berücksichtigt. Durch
YOUR_DATE
das zu konvertierende lokale Datum ersetzen .SELECT DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), YOUR_DATE);
quelle
Während einige dieser Antworten Sie in den Ballpark bringen, können Sie aufgrund der Sommerzeit nicht das tun, was Sie mit beliebigen Daten für SqlServer 2005 und früher versuchen. Wenn ich die Differenz zwischen der aktuellen lokalen und der aktuellen UTC verwende, erhalte ich den Offset, wie er heute existiert. Ich habe keine Möglichkeit gefunden, den Offset für das betreffende Datum zu bestimmen.
Ich weiß jedoch, dass SqlServer 2008 einige neue Datumsfunktionen bietet, mit denen dieses Problem möglicherweise behoben werden kann. Benutzer einer früheren Version müssen sich jedoch der Einschränkungen bewusst sein.
Unser Ansatz ist es, UTC beizubehalten und die Konvertierung auf der Clientseite durchzuführen, wo wir mehr Kontrolle über die Genauigkeit der Konvertierung haben.
quelle
Verwenden Sie für SQL Server 2016 und höher sowie für Azure SQL Database die integrierte
AT TIME ZONE
Anweisung .Für ältere Versionen von SQL Server können Sie meine verwenden SQL Server Zeitzonen - Unterstützung Projekt zu konvertieren zwischen IANA Standardzeitzonen, wie hier aufgelistet .
UTC zu Local ist wie folgt:
SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'America/Los_Angeles')
Lokal zu UTC ist wie folgt:
SELECT Tzdb.LocalToUtc('2015-07-01 00:00:00', 'America/Los_Angeles', 1, 1)
Die numerischen Optionen sind ein Flag zur Steuerung des Verhaltens, wenn die lokalen Zeitwerte von der Sommerzeit beeinflusst werden. Diese sind in der Projektdokumentation ausführlich beschrieben.
quelle
SQL Server 2008 hat einen Typ namens
datetimeoffset
. Es ist wirklich nützlich für diese Art von Sachen.http://msdn.microsoft.com/en-us/library/bb630289.aspx
Dann können Sie die Funktion verwenden
SWITCHOFFSET
, um sie von einer Zeitzone in eine andere zu verschieben, wobei Sie jedoch den gleichen UTC-Wert beibehalten.http://msdn.microsoft.com/en-us/library/bb677244.aspx
rauben
quelle
Hier ist der Code zum Konvertieren einer Zone
DateTime
in eine andere ZoneDateTime
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
Hinweis : Funktioniert
AT TIME ZONE
nur unter SQL Server 2016+ und hat den Vorteil, dass bei der Konvertierung in eine bestimmte Zeitzone automatisch Tageslicht berücksichtigt wirdquelle
AT TIME ZONE
Anrufe (Phrasen?) Aneinander ketten können ! Einfach elegant. Ich habe vorhin gesagt, dass stackoverflow.com/a/44579178/112764 meine Anforderungen erfüllt, aber das ist noch besser. Ein großes Lob.DECLARE @UTCDateTime DATETIME = GETUTCDATE();
DECLARE @ConvertedZoneDateTime DATETIME;
-- 'UTC' to 'India Standard Time' to 'Eastern Standard Time' DATETIME
SET @ConvertedZoneDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time' AT TIME ZONE 'Eastern Standard Time'
SELECT @UTCDateTime AS UTCDATE,@ConvertedZoneDateTime AS EasternStandardTime
Ja, Sie können mehrereAT TIME ZONE
Anrufe verketten, aber Von und Bis reicht für jede Konvertierung und die meisten, die wir brauchtenIch neige dazu, DateTimeOffset für alle Datums- und Zeitspeicher zu verwenden, die nicht mit einem lokalen Ereignis zusammenhängen (z. B. Besprechung / Party usw., 12-15 Uhr im Museum).
So erhalten Sie das aktuelle DTO als 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]
HINWEIS: Ich verwende immer UTC, wenn ich über das Kabel sende ... clientseitige JS können problemlos zu / von lokalen UTC gelangen. Siehe:
new Date().toJSON()
...Der folgende JS behandelt das Parsen eines UTC / GMT-Datums im ISO8601-Format auf eine lokale Datums- / Uhrzeitangabe.
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; }; }
quelle
Ja, bis zu einem gewissen Grad, wie hier beschrieben .
Der Ansatz, den ich (vor 2008) verwendet habe, besteht darin, die Konvertierung in der .NET-Geschäftslogik durchzuführen, bevor sie in die Datenbank eingefügt wird.
quelle
Sie können die Funktion GETUTCDATE () verwenden, um die UTC-Datumszeit abzurufen. Wahrscheinlich können Sie den Unterschied zwischen GETUTCDATE () und GETDATE () auswählen und diesen Unterschied verwenden, um Ihre Daten an UTC anzupassen
Ich stimme jedoch der vorherigen Nachricht zu, dass es viel einfacher ist, die richtige Datums- und Uhrzeitangabe in der Geschäftsschicht zu steuern (z. B. in .NET).
quelle
Beispielnutzung:
SELECT Getdate=GETDATE() ,SysDateTimeOffset=SYSDATETIMEOFFSET() ,SWITCHOFFSET=SWITCHOFFSET(SYSDATETIMEOFFSET(),0) ,GetutcDate=GETUTCDATE() GO
Kehrt zurück:
quelle