Konvertieren Sie die Datetime-Spalte von UTC in die Ortszeit in der select-Anweisung


208

Ich führe einige SQL-Auswahlabfragen durch und möchte meine UTC-Datums- / Uhrzeitspalte in die Ortszeit konvertieren, um sie in meinen Abfrageergebnissen als Ortszeit anzuzeigen. Beachten Sie, dass ich diese Konvertierung NICHT über Code durchführen möchte, sondern wenn ich manuelle und zufällige SQL-Abfragen für meine Datenbanken durchführe.


Scheint diese Frage Ihren Umständen ähnlich zu sein? stackoverflow.com/questions/3404646/…
Taryn East

Antworten:


321

Sie können dies unter SQL Server 2008 oder höher wie folgt tun:

SELECT CONVERT(datetime, 
               SWITCHOFFSET(CONVERT(datetimeoffset, 
                                    MyTable.UtcColumn), 
                            DATENAME(TzOffset, SYSDATETIMEOFFSET()))) 
       AS ColumnInLocalTime
FROM MyTable

Sie können auch weniger ausführlich vorgehen:

SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), MyTable.UtcColumn) 
       AS ColumnInLocalTime
FROM MyTable

Was immer Sie tun, nicht verwenden , -um Termine zu subtrahieren, da der Betrieb nicht atomar ist, und Sie werden gelegentlich unbestimmte Ergebnisse erhalten auf Grund der Rasse Bedingungen zwischen dem System Datetime und der lokalen Datetime werden zu unterschiedlichen Zeitpunkten geprüft (dh nicht-atomar) .

Bitte beachten Sie, dass diese Antwort die Sommerzeit nicht berücksichtigt. Wenn Sie eine Sommerzeitanpassung vornehmen möchten, lesen Sie bitte auch die folgende SO-Frage:

So erstellen Sie die Start- und Endfunktion für die Sommerzeit in SQL Server


38
Gibt es eine Möglichkeit, dieses Konto für die Sommerzeit zu nutzen?
Steve

15
Ich sehe hier nicht den Namen einer Zeitzone, daher ist dies falsch. Es ist eine wirklich schlechte Idee anzunehmen, dass Sie durch Rechnen in die Ortszeit konvertieren können
JonnyRaa

7
@MichaelGoldshteyn Wenn Sie einen Zeitzonenversatz haben, wissen Sie immer noch nicht, in welcher logischen Zeitzone sich eine Zeit befindet. Zeitzonen sind soziale Dinge und können von Regierungen an verschiedenen Punkten geändert werden. Der Versatz für eine Zeitzone kann zu verschiedenen Zeitpunkten / in der Geschichte unterschiedlich sein (Sommerzeit ist eine gemeinsame Zeit). Sie versetzen eine Zeit um den aktuellen Versatz von UTC ... Ein weiterer Punkt ist, dass dies die Zeitzone des Servers und nicht des Clients angibt. Dies könnte ein weiteres Problem sein, wenn Sie in einem anderen Land hosten.
JonnyRaa

4
@Niloofar Die einfache Antwort ist, dass Sie nicht und sollten nicht. Datenzeiten sollten immer in UTC gespeichert werden (vorzugsweise basierend auf der Uhr des Datenbankservers, nicht der Uhr des Webservers, des Anwendungsservers und definitiv nicht der Uhr des Clients). Das Anzeigen dieser Datumszeit ist eine Funktion für die Benutzeroberflächenebene und für die Konvertierung der Datumszeit in das gewünschte Format (einschließlich einer Zeitzone, falls erforderlich) verantwortlich.
Robert McKee

11
Für alle, die SQL Azure verwenden, funktioniert dieser Ansatz nicht, da alle Datums- / Uhrzeitfunktionen UTC zurückgeben. Wenn Sie also GETDATE () mit GETUTCDATE () vergleichen, erhalten Sie nichts, mit dem Sie arbeiten können, und Ihr Ergebnis ist das gleiche, mit dem Sie begonnen haben.
Brian Surowiec

59

Ich fand keines dieser Beispiele hilfreich, um eine als UTC gespeicherte Datumszeit auf eine Datumszeit in einer bestimmten Zeitzone zu übertragen (NICHT die Zeitzone des Servers, da Azure SQL-Datenbanken als UTC ausgeführt werden). So habe ich damit umgegangen. Es ist nicht elegant, aber einfach und gibt Ihnen die richtige Antwort, ohne andere Tabellen zu pflegen:

select CONVERT(datetime, SWITCHOFFSET(dateTimeField, DATEPART(TZOFFSET, 
dateTimeField AT TIME ZONE 'Eastern Standard Time')))

4
Funktioniert nur für 2016 und verwendet die Systemregistrierung. Aber großartige Lösung für Azure.
Dan Cundy

2
Dieser funktioniert für azurblaue Zeiten, die in UTC gespeichert sind, danke Jungs
Null

3
Hier ist eine Liste der Zeichenfolgen, die Sie für die Zeitzonen verwenden können: stackoverflow.com/a/7908482/631277
Matt Kemp

1
Wenn SQL 2016 und die Verwendung von AT TIME ZONESyntax, betrachtet stackoverflow.com/a/44941536/112764 - können Sie Kette mehr Konvertierungen zusammen , indem einfach mehr verketten at time zone <blah>s.
NateJ

3
Dies ist auch ein wenig seltsam, aber einige sehr grundlegende Tests scheinen auch zu funktionieren - dateTimeField AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time'- nur die AT TIME ZONEAussagen zu verketten . (@NateJ erwähnte dies oben, den ich jetzt sehe)
David Mohundro

22

Wenn Ihre lokale Datums- und Uhrzeitangabe angegeben ist Eastern Standard Timeund Sie von UTC in diese konvertieren möchten, können Sie in Azure SQL und SQL Server 2016 und höher Folgendes tun:

SELECT YourUtcColumn AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time' AS
       LocalTime
FROM   YourTable

Die vollständige Liste der Zeitzonennamen finden Sie unter:

SELECT * FROM sys.time_zone_info 

Und ja, die Zeitzonen sind schlecht benannt - obwohl dies der Eastern Standard TimeFall ist , wird die Sommerzeit berücksichtigt.


2
Zeitzonen und Offsets finden Sie auch in SQL Server hier: SELECT * FROM sys.time_zone_info
rayzinnz

21

Wenn Sie eine andere Konvertierung als den Standort Ihres Servers benötigen, können Sie mit dieser Funktion einen Standardoffset übergeben und die US-Sommerzeit berücksichtigen:

-- =============================================
-- Author:      Ron Smith
-- Create date: 2013-10-23
-- Description: Converts UTC to DST
--              based on passed Standard offset
-- =============================================
CREATE FUNCTION [dbo].[fn_UTC_to_DST]
(
    @UTC datetime,
    @StandardOffset int
)
RETURNS datetime
AS
BEGIN

    declare 
        @DST datetime,
        @SSM datetime, -- Second Sunday in March
        @FSN datetime  -- First Sunday in November

    -- get DST Range
    set @SSM = datename(year,@UTC) + '0314' 
    set @SSM = dateadd(hour,2,dateadd(day,datepart(dw,@SSM)*-1+1,@SSM))
    set @FSN = datename(year,@UTC) + '1107'
    set @FSN = dateadd(second,-1,dateadd(hour,2,dateadd(day,datepart(dw,@FSN)*-1+1,@FSN)))

    -- add an hour to @StandardOffset if @UTC is in DST range
    if @UTC between @SSM and @FSN
        set @StandardOffset = @StandardOffset + 1

    -- convert to DST
    set @DST = dateadd(hour,@StandardOffset,@UTC)

    -- return converted datetime
    return @DST

END

GO

2
Ron Smith Ich weiß, dass dies ein alter Beitrag ist, aber ich war neugierig, was die hartcodierten '0314' und '1107' für den Erhalt der Sommerzeit bedeuten. Es scheinen fest codierte Tage zu sein, die sich aufgrund von DTS ändern. Warum sollten Sie dies hart codieren, wenn es ein berechnetes Datum sein sollte, da sich die Tage basierend darauf ändern, wo im Kalender der zweite Sonntag im März und der erste Sonntag im November fallen. Die hart codierten Tage würden diesen Code grundlegend fehlerhaft machen.
Mike

2
Gute Frage :) Dies sind die maximalen Daten, an denen der zweite Sonntag im März und der erste Sonntag im November auftreten können. In den folgenden Zeilen werden die Variablen auf das tatsächliche Datum gesetzt.
Ron Smith

8

Verwenden neuer SQL Server 2016-Möglichkeiten:

CREATE FUNCTION ToLocalTime(@dtUtc datetime, @timezoneId nvarchar(256))
RETURNS datetime
AS BEGIN

return @dtUtc AT TIME ZONE 'UTC' AT TIME ZONE @timezoneId

/* -- second way, faster

return SWITCHOFFSET(@dtUtc , DATENAME(tz, @dtUtc AT TIME ZONE @timezoneId))

*/

/* -- third way

declare @dtLocal datetimeoffset
set @dtLocal = @dtUtc AT TIME ZONE @timezoneId
return dateadd(minute, DATEPART (TZoffset, @dtLocal), @dtUtc)

*/

END
GO

Aber die clr-Prozedur funktioniert fünfmal schneller: '- (

Beachten Sie, dass sich der Versatz für eine Zeitzone auf Winter- oder Sommerzeit ändern kann. Beispielsweise

select cast('2017-02-08 09:00:00.000' as datetime) AT TIME ZONE 'Eastern Standard Time'
select cast('2017-08-08 09:00:00.000' as datetime) AT TIME ZONE 'Eastern Standard Time'

Ergebnisse:

2017-02-08 09:00:00.000 -05:00
2017-08-08 09:00:00.000 -04:00

Sie können nicht einfach einen konstanten Versatz hinzufügen.


5

Wenn das Aktivieren der CLR in Ihrer Datenbank eine Option ist und die Zeitzone des SQL-Servers verwendet wird, kann sie ganz einfach in .Net geschrieben werden.

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlDateTime fn_GetLocalFromUTC(SqlDateTime UTC)
    {
        if (UTC.IsNull)
            return UTC;

        return new SqlDateTime(UTC.Value.ToLocalTime());
    }
}

Ein UTC-Datum / Uhrzeit-Wert wird eingegeben und der lokale Datum / Uhrzeit-Wert relativ zum Server wird ausgegeben. Nullwerte geben null zurück.


5

Es gibt keine einfache Möglichkeit, dies korrekt UND allgemein zu tun.

Zunächst muss verstanden werden, dass der Versatz vom fraglichen Datum, der Zeitzone UND der Sommerzeit abhängt. GetDate()-GetUTCDategibt Ihnen heute nur den Offset an der TZ des Servers, der nicht relevant ist.

Ich habe nur zwei funktionierende Lösungen gesehen und viel gesucht.

1) Eine benutzerdefinierte SQL-Funktion mit einigen Tabellen mit Basisdaten wie Zeitzonen und DST-Regeln pro TZ. Arbeiten aber nicht sehr elegant. Ich kann es nicht posten, da ich den Code nicht besitze.

BEARBEITEN: Hier ist ein Beispiel für diese Methode https://gist.github.com/drumsta/16b79cee6bc195cd89c8

2) Fügen Sie der Datenbank eine .net-Assembly hinzu. .Net kann dies sehr einfach tun. Dies funktioniert sehr gut, aber der Nachteil ist, dass Sie mehrere Parameter auf Serverebene konfigurieren müssen und die Konfiguration leicht beschädigt werden kann, z. B. wenn Sie die Datenbank wiederherstellen. Ich benutze diese Methode, kann sie aber nicht posten, da mir der Code nicht gehört.


4

Keines davon hat bei mir funktioniert, aber das unten hat zu 100% funktioniert. Hoffe, dies kann anderen helfen, die versuchen, es so zu konvertieren, wie ich es war.

CREATE FUNCTION [dbo].[fn_UTC_to_EST]
(
    @UTC datetime,
    @StandardOffset int
)
RETURNS datetime
AS
BEGIN

declare 
    @DST datetime,
    @SSM datetime, -- Second Sunday in March
    @FSN datetime  -- First Sunday in November
-- get DST Range
set @SSM = DATEADD(dd,7 + (6-(DATEDIFF(dd,0,DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 2,0))%7)),DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 2,0))+'02:00:00' 
set @FSN = DATEADD(dd, (6-(DATEDIFF(dd,0,DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 10,0))%7)),DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 10,0)) +'02:00:00'

-- add an hour to @StandardOffset if @UTC is in DST range
if @UTC between @SSM and @FSN
    set @StandardOffset = @StandardOffset + 1

-- convert to DST
set @DST = dateadd(hour,@StandardOffset,@UTC)

-- return converted datetime
return @DST

END

1
Dies sollte die akzeptierte Antwort sein. Das einzige, was ich ändern würde, ist der Name, da er impliziert, dass es sich um die EST-Zeit handelt, wenn es sich tatsächlich um die Ortszeit handelt und das StandardOffset als Parameter übergeben wird.
Greg Gum

Stimmen Sie zu, beste Antwort ... aber anstatt den Offset als Parameter übergeben zu müssen, habe ich diesen im Funktionskörper hinzugefügt:declare @StandardOffset int = datediff (hh, GETUTCDATE(), GETDATE())
Tom Warfield

Weiterverfolgung meines vorherigen Vorschlags - Wenn Sie @StandardOffset berechnen, müssen Sie die Sommerzeitkorrektur nicht durchführen.
Tom Warfield

3

Hier ist eine Version, die Sommerzeit und UTC-Offset berücksichtigt und nicht an ein bestimmtes Jahr gebunden ist.

---------------------------------------------------------------------------------------------------
--Name:     udfToLocalTime.sql
--Purpose:  To convert UTC to local US time accounting for DST
--Author:   Patrick Slesicki
--Date:     3/25/2014
--Notes:    Works on SQL Server 2008R2 and later, maybe SQL Server 2008 as well.
--          Good only for US States observing the Energy Policy Act of 2005.
--          Function doesn't apply for years prior to 2007.
--          Function assumes that the 1st day of the week is Sunday.
--Tests:        
--          SELECT dbo.udfToLocalTime('2014-03-09 9:00', DEFAULT)
--          SELECT dbo.udfToLocalTime('2014-03-09 10:00', DEFAULT)
--          SELECT dbo.udfToLocalTime('2014-11-02 8:00', DEFAULT)
--          SELECT dbo.udfToLocalTime('2014-11-02 9:00', DEFAULT)
---------------------------------------------------------------------------------------------------
ALTER FUNCTION udfToLocalTime
    (
    @UtcDateTime    AS DATETIME
    ,@UtcOffset     AS INT = -8 --PST
    )
RETURNS DATETIME
AS 
BEGIN
    DECLARE 
        @PstDateTime    AS DATETIME
        ,@Year          AS CHAR(4)
        ,@DstStart      AS DATETIME
        ,@DstEnd        AS DATETIME
        ,@Mar1          AS DATETIME
        ,@Nov1          AS DATETIME
        ,@MarTime       AS TIME
        ,@NovTime       AS TIME
        ,@Mar1Day       AS INT
        ,@Nov1Day       AS INT
        ,@MarDiff       AS INT
        ,@NovDiff       AS INT

    SELECT
        @Year       = YEAR(@UtcDateTime)
        ,@MarTime   = CONVERT(TIME, DATEADD(HOUR, -@UtcOffset, '1900-01-01 02:00'))
        ,@NovTime   = CONVERT(TIME, DATEADD(HOUR, -@UtcOffset - 1, '1900-01-01 02:00'))
        ,@Mar1      = CONVERT(CHAR(16), @Year + '-03-01 ' + CONVERT(CHAR(5), @MarTime), 126)
        ,@Nov1      = CONVERT(CHAR(16), @Year + '-11-01 ' + CONVERT(CHAR(5), @NovTime), 126)
        ,@Mar1Day   = DATEPART(WEEKDAY, @Mar1)
        ,@Nov1Day   = DATEPART(WEEKDAY, @Nov1)

    --Get number of days between Mar 1 and DST start date
    IF @Mar1Day = 1 SET @MarDiff = 7
    ELSE SET @MarDiff = 15 - @Mar1Day

    --Get number of days between Nov 1 and DST end date
    IF @Nov1Day = 1 SET @NovDiff = 0
    ELSE SET @NovDiff = 8 - @Nov1Day

    --Get DST start and end dates
    SELECT 
        @DstStart   = DATEADD(DAY, @MarDiff, @Mar1)
        ,@DstEnd    = DATEADD(DAY, @NovDiff, @Nov1)

    --Change UTC offset if @UtcDateTime is in DST Range
    IF @UtcDateTime >= @DstStart AND @UtcDateTime < @DstEnd SET @UtcOffset = @UtcOffset + 1

    --Get Conversion
    SET @PstDateTime = DATEADD(HOUR, @UtcOffset, @UtcDateTime)
    RETURN @PstDateTime
END
GO

3

Ich fand die einmalige Funktion zu langsam, wenn viele Daten vorhanden sind. Also habe ich es getan, indem ich mich einer Tabellenfunktion angeschlossen habe, die eine Berechnung des Stundenunterschieds ermöglicht. Grundsätzlich handelt es sich um Datum / Uhrzeit-Segmente mit dem Stundenversatz. Ein Jahr wäre 4 Reihen. Also die Tabellenfunktion

dbo.fn_getTimeZoneOffsets('3/1/2007 7:00am', '11/5/2007 9:00am', 'EPT')

würde diese Tabelle zurückgeben:

startTime          endTime   offset  isHr2
3/1/07 7:00     3/11/07 6:59    -5    0
3/11/07 7:00    11/4/07 6:59    -4    0
11/4/07 7:00    11/4/07 7:59    -5    1
11/4/07 8:00    11/5/07 9:00    -5    0

Es berücksichtigt die Sommerzeit. Ein Beispiel für die Verwendung finden Sie weiter unten. Den vollständigen Blog-Beitrag finden Sie hier .

select mt.startTime as startUTC, 
    dateadd(hh, tzStart.offset, mt.startTime) as startLocal, 
    tzStart.isHr2
from MyTable mt 
inner join dbo.fn_getTimeZoneOffsets(@startViewUTC, @endViewUTC, @timeZone)  tzStart
on mt.startTime between tzStart.startTime and tzStart.endTime

Es scheint nicht, dass die Sommerzeit korrekt berücksichtigt wird. Ich bin mir nicht sicher, ob Sie davon ausgehen, dass nur die USA existieren und dass sich die Sommerzeitregeln nie ändern.
Vikjon0

@ vikjon0 ja, das Projekt, für das ich das gebaut habe, hatte nur US-Zeitzonen.
JBrooks

2
 declare @mydate2 datetime
 set @mydate2=Getdate()
 select @mydate2 as mydate,
 dateadd(minute, datediff(minute,getdate(),@mydate2),getutcdate())

1

Rons Antwort enthält einen Fehler. Es wird 2:00 Uhr Ortszeit verwendet, wenn das UTC-Äquivalent erforderlich ist. Ich habe nicht genügend Reputationspunkte, um Rons Antwort zu kommentieren, daher wird unten eine korrigierte Version angezeigt:

-- =============================================
-- Author:      Ron Smith
-- Create date: 2013-10-23
-- Description: Converts UTC to DST
--              based on passed Standard offset
-- =============================================
CREATE FUNCTION [dbo].[fn_UTC_to_DST]
(
    @UTC datetime,
    @StandardOffset int
)
RETURNS datetime
AS
BEGIN

declare 
    @DST datetime,
    @SSM datetime, -- Second Sunday in March
    @FSN datetime  -- First Sunday in November
-- get DST Range
set @SSM = datename(year,@UTC) + '0314' 
set @SSM = dateadd(hour,2 - @StandardOffset,dateadd(day,datepart(dw,@SSM)*-1+1,@SSM))
set @FSN = datename(year,@UTC) + '1107'
set @FSN = dateadd(second,-1,dateadd(hour,2 - (@StandardOffset + 1),dateadd(day,datepart(dw,@FSN)*-1+1,@FSN)))

-- add an hour to @StandardOffset if @UTC is in DST range
if @UTC between @SSM and @FSN
    set @StandardOffset = @StandardOffset + 1

-- convert to DST
set @DST = dateadd(hour,@StandardOffset,@UTC)

-- return converted datetime
return @DST

END

Es ist eine Funktion, kein Fehler :) Die meisten Vereinigten Staaten beginnen die Sommerzeit um 2:00 Uhr en.wikipedia.org/wiki/Daylight_saving_time
Ron Smith

@RonSmith Ja, um 2:00 Uhr Ortszeit, die wir in UTC konvertieren müssen, um festzustellen, ob die angegebene UTC-Zeit im DST-Bereich liegt.
jlspublic

1

Der UNIX-Zeitstempel ist lediglich die Anzahl der Sekunden zwischen einem bestimmten Datum und der Unix-Epoche.

SELECT DATEDIFF (SECOND, {d '1970-01-01'}, GETDATE ()) // Dies gibt den UNIX-Zeitstempel in SQL Server zurück

Sie können eine Funktion für die Konvertierung von lokaler Datums- und Uhrzeit in Unix-UTC mithilfe der Länderversatzfunktion in Unix-Zeitstempel in SQL Server erstellen


1

Es ist einfach. Versuchen Sie dies für Azure SQL Server:

SELECT YourDateTimeColumn AT TIME ZONE 'Eastern Standard Time' FROM YourTable

Für lokalen SQL Server:

SELECT CONVERT(datetime2, SWITCHOFFSET(CONVERT(datetimeoffset, gETDATE()), DATENAME(TzOffset, gETDATE() AT TIME ZONE 'Eastern Standard Time'))) FROM YourTable

1
Was passiert damit während der Sommerzeit (da in der Zeitzone ausdrücklich "Eastern Standard Time" steht)?
Markieren Sie

1

Für @@VersionBenutzer von Azure SQL und > = SQL Server 2016 finden Sie unten eine einfache Funktion AT TIME ZONE.

CREATE FUNCTION [dbo].[Global_Convert_UTCTimeTo_LocalTime]
(
   @LocalTimeZone        VARCHAR(50),
   @UTCDateTime          DATETIME
)
RETURNS DATETIME
AS
BEGIN
   DECLARE @ConvertedDateTime DATETIME;

   SELECT @ConvertedDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE @LocalTimeZone
   RETURN @ConvertedDateTime

END
GO

Informationen zu möglichen Wertetypen @LocalTimeZonefinden Sie unter diesem Link oder unterKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones


0

Als Warnung - wenn Sie Folgendes verwenden möchten (beachten Sie die Millisekunden anstelle von Minuten):

    SELECT DATEADD(ms, DATEDIFF(ms, GETUTCDATE(), GETDATE()), MyTable.UtcColumn) 
    AS ColumnInLocalTime
    FROM MyTable

Beachten Sie, dass der DATEDIFF-Teil nicht immer dieselbe Nummer zurückgibt. Verwenden Sie es also nicht, um DateTimes auf Millisekunden zu vergleichen.


0

Ich habe festgestellt, dass diese Funktion schneller ist als andere Lösungen, die eine separate Tabelle oder Schleifen verwenden. Es ist nur eine grundlegende Fallaussage. Da alle Monate zwischen April und Oktober einen Versatz von -4 Stunden (Eastern Time) haben, müssen wir nur ein paar weitere Fallzeilen für die Randtage hinzufügen. Andernfalls beträgt der Offset -5 Stunden.

Dies ist spezifisch für eine Konvertierung von UTC zu Eastern Time. Bei Bedarf können jedoch zusätzliche Zeitzonenfunktionen hinzugefügt werden.

USE [YourDatabaseName]
GO

/****** Object:  UserDefinedFunction [dbo].[ConvertUTCtoEastern]    Script Date: 11/2/2016 5:21:52 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE FUNCTION [dbo].[ConvertUTCtoEastern]
(
@dtStartDate DATETIME
)
RETURNS DATETIME
AS
BEGIN
DECLARE @Working DATETIME
DECLARE @Returned DATETIME

SET @Working = @dtStartDate
SET @Working = 
case when month(@Working) between 4 and 10 then dateadd(HH,-4,@Working) 
     when @Working between '2017-03-12' and '2017-11-05' then dateadd(HH,-4,@Working) 
     when @Working between '2016-03-13' and '2016-11-06' then dateadd(HH,-4,@Working) 
     when @Working between '2015-03-08' and '2015-11-01' then dateadd(HH,-4,@Working) 
     when @Working between '2014-03-09' and '2014-11-02' then dateadd(HH,-4,@Working) 
     when @Working between '2013-03-10' and '2013-11-03' then dateadd(HH,-4,@Working) 
     when @Working between '2012-03-11' and '2012-11-04' then dateadd(HH,-4,@Working) 
else dateadd(HH,-5,@Working) end

SET @Returned = @Working

RETURN @Returned

END


GO

0

Dies sollte in der Lage sein, Serverzeit mit Sommerzeit zu erhalten

declare @dt datetime
set @dt = getutcdate() -- GMT equivalent

sysdatetimeoffset berücksichtigt die Sommerzeit

select [InputTime] = @dt
       , [LocalTime2] = dateadd(mi, datediff(mi, sysdatetimeoffset(),getdate()), @dt) 

0

Erste Funktion: konfiguriert für die italienische Zeitzone (+1, +2), Datum wechseln: letzter Sonntag im März und Oktober, Rückgabe der Differenz zwischen der aktuellen Zeitzone und der Datum / Uhrzeit als Parameter.

Returns:
current timezone < parameter timezone ==> +1
current timezone > parameter timezone ==> -1
else 0

Der Code lautet:

CREATE FUNCTION [dbo].[UF_ADJUST_OFFSET]
(
    @dt_utc datetime2(7)
)
RETURNS INT
AS
BEGIN


declare @month int,
        @year int,
        @current_offset int,
        @offset_since int,
        @offset int,
        @yearmonth varchar(8),
        @changeoffsetdate datetime2(7)

declare @lastweek table(giorno datetime2(7))

select @current_offset = DATEDIFF(hh, GETUTCDATE(), GETDATE())

select @month = datepart(month, @dt_utc)

if @month < 3 or @month > 10 Begin Set @offset_since = 1 Goto JMP End

if @month > 3 and @month < 10 Begin Set @offset_since = 2 Goto JMP End

--If i'm here is march or october
select @year = datepart(yyyy, @dt_utc)

if @month = 3
Begin

Set @yearmonth = cast(@year as varchar) + '-03-'

Insert Into @lastweek Values(@yearmonth + '31 03:00:00.000000'),(@yearmonth + '30 03:00:00.000000'),(@yearmonth + '29 03:00:00.000000'),(@yearmonth + '28 03:00:00.000000'),
                         (@yearmonth + '27 03:00:00.000000'),(@yearmonth + '26 03:00:00.000000'),(@yearmonth + '25 03:00:00.000000')

--Last week of march
Select @changeoffsetdate = giorno From @lastweek Where  datepart(weekday, giorno) = 1

    if @dt_utc < @changeoffsetdate 
    Begin 
        Set @offset_since = 1 
    End Else Begin
        Set @offset_since = 2
    End
End

if @month = 10
Begin

Set @yearmonth = cast(@year as varchar) + '-10-'

Insert Into @lastweek Values(@yearmonth + '31 03:00:00.000000'),(@yearmonth + '30 03:00:00.000000'),(@yearmonth + '29 03:00:00.000000'),(@yearmonth + '28 03:00:00.000000'),
                         (@yearmonth + '27 03:00:00.000000'),(@yearmonth + '26 03:00:00.000000'),(@yearmonth + '25 03:00:00.000000')

--Last week of october
Select @changeoffsetdate = giorno From @lastweek Where  datepart(weekday, giorno) = 1

    if @dt_utc > @changeoffsetdate 
    Begin 
        Set @offset_since = 1 
    End Else Begin
        Set @offset_since = 2
    End
End

JMP:

if @current_offset < @offset_since Begin
    Set @offset = 1
End Else if @current_offset > @offset_since Set @offset = -1 Else Set @offset = 0

Return @offset

END

Dann die Funktion, die das Datum konvertiert

CREATE FUNCTION [dbo].[UF_CONVERT]
(
    @dt_utc datetime2(7)
)
RETURNS datetime
AS
BEGIN

    declare @offset int


    Select @offset = dbo.UF_ADJUST_OFFSET(@dt_utc)

    if @dt_utc >= '9999-12-31 22:59:59.9999999'
        set @dt_utc = '9999-12-31 23:59:59.9999999'
    Else
        set @dt_utc = (SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), @dt_utc) )

    if @offset <> 0
        Set @dt_utc = dateadd(hh, @offset, @dt_utc)

    RETURN @dt_utc

END

0

- Holen Sie sich die indische Standardzeit von utc

CREATE FUNCTION dbo.getISTTime
(
@UTCDate datetime
)
RETURNS datetime
AS
BEGIN

    RETURN dateadd(minute,330,@UTCDate)

END
GO

0

Dies kann ohne Funktion erfolgen. Der folgende Code konvertiert eine UTC-Zeit in die Bergzeit, wobei die Sommerzeit berücksichtigt wird. Passen Sie alle -6- und -7-Zahlen entsprechend an Ihre Zeitzone an (dh für EST würden Sie auf -4 bzw. -5 einstellen).

--Adjust a UTC value, in the example the UTC field is identified as UTC.Field, to account for daylight savings time when converting out of UTC to Mountain time.
CASE
    --When it's between March and November, it is summer time which is -6 from UTC
    WHEN MONTH ( UTC.Field ) > 3 AND MONTH ( UTC.Field ) < 11 
        THEN DATEADD ( HOUR , -6 , UTC.Field )
    --When its March and the day is greater than the 14, you know it's summer (-6)
    WHEN MONTH ( UTC.Field ) = 3
        AND DATEPART ( DAY , UTC.Field ) >= 14 
        THEN
            --However, if UTC is before 9am on that Sunday, then it's before 2am Mountain which means it's still Winter daylight time.
            CASE 
                WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1 
                    AND UTC.Field < '9:00'
                    --Before 2am mountain time so it's winter, -7 hours for Winter daylight time
                    THEN DATEADD ( HOUR , -7 , UTC.Field )
                --Otherwise -6 because it'll be after 2am making it Summer daylight time
                ELSE DATEADD ( HOUR , -6 , UTC.Field )
            END
    WHEN MONTH ( UTC.Field ) = 3
        AND ( DATEPART ( WEEKDAY , UTC.Field ) + 7 ) <= DATEPART ( day , UTC.Field ) 
        THEN 
            --According to the date, it's moved onto Summer daylight, but we need to account for the hours leading up to 2am if it's Sunday
            CASE 
                WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1 
                    AND UTC.Field < '9:00'
                    --Before 9am UTC is before 2am Mountain so it's winter Daylight, -7 hours
                    THEN DATEADD ( HOUR , -7 , UTC.Field )
                --Otherwise, it's summer daylight, -6 hours
                ELSE DATEADD ( HOUR , -6 , UTC.Field )
            END
    --When it's November and the weekday is greater than the calendar date, it's still Summer so -6 from the time
    WHEN MONTH ( UTC.Field ) = 11
        AND DATEPART ( WEEKDAY , UTC.Field ) > DATEPART ( DAY , UTC.Field ) 
        THEN DATEADD ( HOUR , -6 , UTC.Field )
    WHEN MONTH ( UTC.Field ) = 11
        AND DATEPART ( WEEKDAY , UTC.Field ) <= DATEPART ( DAY , UTC.Field ) 
            --If the weekday is less than or equal to the calendar day it's Winter daylight but we need to account for the hours leading up to 2am.
            CASE 
                WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1 
                    AND UTC.Field < '8:00'
                    --If it's before 8am UTC and it's Sunday in the logic outlined, then it's still Summer daylight, -6 hours
                    THEN DATEADD ( HOUR , -6 , UTC.Field )
                --Otherwise, adjust for Winter daylight at -7
                ELSE DATEADD ( HOUR , -7 , UTC.Field )
            END
    --If the date doesn't fall into any of the above logic, it's Winter daylight, -7
    ELSE
        DATEADD ( HOUR , -7 , UTC.Field )
END

0

Sie müssen den String neu formatieren und zur richtigen Zeit konvertieren. In diesem Fall brauchte ich Zulu-Zeit.

Declare @Date datetime;
Declare @DateString varchar(50);
set @Date = GETDATE(); 
declare @ZuluTime datetime;

Declare @DateFrom varchar (50);
Declare @DateTo varchar (50);
set @ZuluTime = DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), @Date);
set @DateString =  FORMAT(@ZuluTime, 'yyyy-MM-ddThh:mm:ssZ', 'en-US' )  
select @DateString;

0

Bester Weg für Oracle:

Mit fest codierter Datumszeit:

SELECT TO_CHAR(CAST((FROM_TZ(CAST(TO_DATE('2018-10-27 21:00', 'YYYY-MM-DD HH24:MI') AS TIMESTAMP), 'UTC') AT  TIME ZONE 'EET') AS DATE), 'YYYY-MM-DD HH24:MI') UTC_TO_EET FROM DUAL

Result: 2018-10-28 00:00

Mit Spalten- und Tabellennamen:

SELECT TO_CHAR(CAST((FROM_TZ(CAST(COLUMN_NAME AS TIMESTAMP), 'UTC') AT  TIME ZONE 'EET') AS DATE), 'YYYY-MM-DD HH24:MI') UTC_TO_EET FROM TABLE_NAME

0

Ich habe Code, um UTC-zu-Lokal- und Lokal-zu-UTC-Zeiten auszuführen, der die Konvertierung mit Code wie diesem ermöglicht

DECLARE @usersTimezone VARCHAR(32)='Europe/London'
DECLARE @utcDT DATETIME=GetUTCDate()
DECLARE @userDT DATETIME=[dbo].[funcUTCtoLocal](@utcDT, @usersTimezone)

und

DECLARE @usersTimezone VARCHAR(32)='Europe/London'
DECLARE @userDT DATETIME=GetDate()
DECLARE @utcDT DATETIME=[dbo].[funcLocaltoUTC](@userDT, @usersTimezone)

Die Funktionen können alle oder eine Teilmenge von Zeitzonen in der IANA / TZDB unterstützen, wie von NodaTime bereitgestellt - die vollständige Liste finden Sie unter https://nodatime.org/TimeZones

Beachten Sie, dass mein Anwendungsfall bedeutet, dass ich nur ein "aktuelles" Fenster benötige, das die Umrechnung von Zeiten im Bereich von etwa +/- 5 Jahren ermöglicht. Dies bedeutet, dass die von mir verwendete Methode wahrscheinlich nicht für Sie geeignet ist, wenn Sie einen sehr langen Zeitraum benötigen, da Code für jedes Zeitzonenintervall in einem bestimmten Datumsbereich generiert wird.

Das Projekt ist auf GitHub: https://github.com/elliveny/SQLServerTimeConversion

Dadurch wird gemäß diesem Beispiel SQL-Funktionscode generiert


0

Wenn Sie die Daten als UTC-Datum in der Datenbank speichern, können Sie so einfach wie möglich vorgehen

select 
 [MyUtcDate] + getdate() - getutcdate()
from [dbo].[mytable]

Dies war vom Ort des Servers aus immer lokal und Sie fummeln nicht an AT herum TIME ZONE 'your time zone name'. Wenn Ihre Datenbank in eine andere Zeitzone wie eine Client-Installation verschoben wird, kann eine fest codierte Zeitzone Sie beißen.


-1

Hier ist eine einfachere, die dst berücksichtigt

CREATE FUNCTION [dbo].[UtcToLocal] 
(
    @p_utcDatetime DATETIME 
)
RETURNS DATETIME
AS
BEGIN
    RETURN DATEADD(MINUTE, DATEDIFF(MINUTE, GETUTCDATE(), @p_utcDatetime), GETDATE())
END

6
Die Sommerzeit wird dabei nicht berücksichtigt. Probieren Sie es einfach aus : SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, GETUTCDATE(), '20150101'), GETDATE()). Ich bin derzeit in der MESZ (UTC + 2), aber die Sommerzeit wird am Neujahrstag nicht wirksam, sodass die richtige Antwort für mich der 1. Januar 2015 um 01:00 Uhr wäre. Ihre Antwort wird wie die akzeptierte Antwort am 1. Januar 2015 um 02:00 Uhr zurückgegeben.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.