it-swarm.com.de

SQL Server 2008 - Konvertieren von GMT (UTC) -Datenzeit in lokale Datenzeit

Ich habe einen Einfügeprozess, der GETDATE() als einen der Werte übergibt, da jeder Einfügevorgang auch speichert, wann er eingefügt wurde. Dies wird in SQL Azure gehostet, das GMT verwendet.

Wenn ich Nachrichten erhalte, ist das GMT-Datum für jede Nachricht in ihren Zeitstempelspalten gespeichert. Wie konvertiere ich dies in die lokale datetime für jeden Ort, an dem Sie gerade auf meine Seite zugreifen?

Vielen Dank.

10
slandau

Sie könnten so etwas tun:

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

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

oder

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

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

Abgesehen von der Sommerzeitfrage, vereinfachen Sie die Vereinfachung mit:

yourDateTime - getutcdate() + getdate()
5
bwperrin

Für MST als Beispiel ... Wenn man bedenkt, dass jeder DTM bereits in GMT gespeichert ist, vereinfacht dies die Dinge.

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

Wenn Ihr lokales Datum/Uhrzeit etwas anderes als GMT/UTC ist, möchten Sie wahrscheinlich Folgendes verwenden:.

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

Hier ist der Zusammenbruch.

  • SWITCHOFFSET - konvertiert einen DateTimeOffset-Wert in eine andere Zeitzone, wobei der Versatz beibehalten wird.
  • TODATETIMEOFFSET - Konvertiert einen DateTime-Wert in einen DateTimeOffset-Wert zu einer angegebenen Zeitzone.
  • DATEPART - In diesem Fall wird die Zeitzone als Teil der lokalen Datumszeit abgerufen.
  • '+00:00' - der Zielversatz, im zweiten Beispiel ist das UTC/GMT-Ziel, vom lokalen ... das vorherige Beispiel ist MST.

HINWEIS/WARNUNG: Ich glaube nicht, dass dies die Sommerzeit berücksichtigt, die für Sie möglicherweise ein Problem darstellt. Wenn keine absolute Konservierung erforderlich ist, können Sie einfach eine sekundäre Spalte mit der groben Konvertierung hinzufügen und sicher vorgehen.

Sie können die Logik in einen Funktionsaufruf abstrahieren, um die Erhaltung der DST zu berücksichtigen ... es sollte jedoch nicht übermäßig schwierig sein.

1
Tracker1
/*
=============================================
 Author:        Mark Griffiths
 Create date:   29/05/2018
 Description:   BST runs from 02:00AM on the last Sunday of March to the same time on the last Sunday of October.       
    The Series of DATEDIFFs and DATEADDS below function as follows
    1   ●   Count the number of months there have been between the given date and start of computer time
    2   ●   Add that number of months to the end of the first month to get the end of the given month
    3   ●   Count the number of days there have been between the end of the given month and the first Saturday
    4   ●   Add that number of days to the calculated end of the given month
    5   ●   Add Two hours to that time as the clocks go back at 02:00 in the morning

    I know that the tabbing below makes it all look odd, but the description above is the best way I could find to comment things, given the nesting...
    The comments in the code below should help find the nesting levels and the numbers refer to the bullet points above.
=============================================
-- Test Variables --
DECLARE @GMTime DATETIME2(3) = '2018-05-01 12:00:00.000'
*/

    DECLARE @RealTime As DATETIME2(3)
    DECLARE @Year VARCHAR(4)
    SET @Year = CONVERT(VARCHAR,DATEPART(YEAR,@GMTime))
    DECLARE @StartOfBST AS DATETIME
    DECLARE @EndOfBST AS DATETIME
    SELECT
        @StartOfBST =
        DATEADD     -----------------------------------------------------------------------------------------
            (                                                       --                                      |
             HOUR                                                   --                                      |
            ,2                                                      --                                      |
            ,DATEADD    -----------------------------------------------------------------------------       |
                (                                                   --                              |       |
                 DAY                                                --                              |       |
                ,DATEDIFF       -------------------------------------------------------------       |       |
                    (                                               --                      |       |       |
                     DAY                                            --                      |       |       |
                    ,'19000107'                                     --                      |       |       5
                    ,DATEADD            ---------------------------------------------       |       |       |
                        (                                           --              |       3       4       |
                         MONTH                                      --              |       |       |       |
                        ,DATEDIFF(MONTH,0,CONVERT(DATE,'03/01/' + @Year)) -- 1      2       |       |       |
                        ,CONVERT(DATE,'01/31/1900')                 --              |       |       |       |
                        )               ---------------------------------------------       |       |       |
                    )/7*7       -------------------------------------------------------------       |       |
                    ,'19000107'                                     --                              |       |
                )               ---------------------------------------------------------------------       |
            ),      -----------------------------------------------------------------------------------------
    @EndOfBST =
        DATEADD(HOUR,2,DATEADD(day,DATEDIFF(day,'19000107',DATEADD(month,DATEDIFF(MONTH,0,CONVERT(DATE,'10/01/' + @Year)),30))/7*7,'19000107'))
    SET @RealTime = CASE
                    WHEN @GMTime BETWEEN @StartOfBST AND @EndOfBST THEN DATEADD(HOUR,-1,@GMTime)
                    ELSE @GMTime
                END
RETURN @RealTime;
--SELECT @RealTime
END

* EDIT: CONVERT(DATE,'01/30/1900') wurde in CONVERT(DATE,'01/31/1900') geändert, da der Januar seit 45 v. Chr. 31 Tage hatte. Dies führte manchmal zu einem falschen Ergebnis für 2019 und für alle anderen, bei denen der letzte Sonntag im März der 31. ist.

0

Hier ist eine Funktion, die mit historischen Daten arbeitet. Ich habe es für britische Sommerzeit geschrieben - was leider am letzten Sonntag der Monate März und Oktober der Fall ist, was die Logik ein wenig verworren lässt.

Grundsätzlich sucht das hartcodierte Datum 01/03 nach dem letzten Sonntag im März und 01/10 sucht nach dem letzten Sonntag im Oktober (was bedeutet, dass die Uhren vor- und zurückgehen). HINWEIS: WENN IHR SERVER IS VERWENDUNG NATIVE US-TERMINE UMGEKEHRT, ZWEI DATUMEILE AUF 03/01 und 10/01 UMKEHREN !!!!

Sie füttern also ein UTC-Datum und es wird automatisch ermittelt, ob ein historisches Datum BST oder GMT ist. Nicht das Beste für große Datenmengen, aber es ist eine Lösung.

Führen Sie dieses Skript aus, um die Funktion zu erstellen, und rufen Sie sie in Ihrer Auswahl inline auf. SQL 2008 hat ein Problem mit benutzerdefinierten Funktionen. Es scheint, dass es eine Redline unter dem Code gibt, die jedoch weiterhin ausgeführt wird, solange Sie das dbo-Präfix verwenden (SELECT dbo.UTCConvert (Ihr Datum), um es auszuführen).

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