Wie kann ich bigint (UNIX-Zeitstempel) in SQL Server in datetime konvertieren?

Antworten:

57

Versuchen:

CREATE FUNCTION dbo.fn_ConvertToDateTime (@Datetime BIGINT)
RETURNS DATETIME
AS
BEGIN
    DECLARE @LocalTimeOffset BIGINT
           ,@AdjustedLocalDatetime BIGINT;
    SET @LocalTimeOffset = DATEDIFF(second,GETDATE(),GETUTCDATE())
    SET @AdjustedLocalDatetime = @Datetime - @LocalTimeOffset
    RETURN (SELECT DATEADD(second,@AdjustedLocalDatetime, CAST('1970-01-01 00:00:00' AS datetime)))
END;
GO
KM.
quelle
2
+1 Für die UTC-> lokale Konvertierung. Beachten Sie, dass die Sommer- / Winterzeit weiterhin ausgeschaltet ist, wenn Sie versuchen, den 10. Juni im Februar zu übersetzen.
Andomar
11
-1 für die UTC-> lokale Konvertierung. Die Sommerzeit wird nicht richtig gehandhabt. Für mich ist das falsch.
Pavel Horal
+1 für die kreative Lösung! Funktioniert super. Zu Ihrer Information, es gibt einen Syntaxfehler in der SQL. Das Semikolon am Ende der ersten Zeile "DECLARE" muss entfernt werden, da ein Komma folgt.
Seth
2
Es funktioniert nicht bei mir. Ich versuche es mit 1517270400000 und erhalte den folgenden Fehler: Arithmetischer Überlauffehler beim Konvertieren des Ausdrucks in den Datentyp int.
Dänisch
1
Außerdem wurde ein Überlauf erhalten, der normalerweise bedeutet, dass Millisekunden beteiligt sind. Er wurde einfach wie folgt gelöst: Wählen Sie dbo.fn_ConvertToDateTime (src_column / 1000) aus src_table aus.
access_granted
302

Das hat bei mir funktioniert:

Select
    dateadd(S, [unixtime], '1970-01-01')
From [Table]

Im Fall irgendwelche fragt man sich , warum 1970-01-01, Dies nennt man Epoch Zeit .

Unten ist ein Zitat aus Wikipedia:

Die Anzahl der Sekunden, die seit 00:00:00 Coordinated Universal Time (UTC), Donnerstag, 1. Januar 1970, [1] [Anmerkung 1] ohne Schaltsekunden vergangen sind.

Daniel Little
quelle
17
Dies sollte als korrekt markiert werden. Ich wünschte, ich könnte diese Antwort jedes Mal wieder verbessern, wenn ich hier
lande
2
@ BenDundee Ich stimme dir wirklich zu. Was für eine elegante Lösung. Ich suchte überall nach einer Formel und entschied mich schließlich für eine, nur um erneut suchen zu müssen, als ich eine Woche später auf Fehler stieß. Zum Glück habe ich diesen beim zweiten Durchgang gefunden.
Einseitiger
1
Ich habe diese Lösung verwendet. Dieses formatierte Datum war mit anderen Daten verknüpft, also hatte ich einen Varchar ... Einfach! Sie müssen sich nicht die Mühe machen, diese Protokolle in der Anwendung zu formatieren. Es traten jedoch einige wilde Zeitzonenprobleme auf! Meine Daten verwendeten die UTC-Zeitzone anstelle der Zeitzone des Kunden :(
gustavohenke
2
@ Whitecat Weiß nicht, ob Sie Ihr Problem bereits gelöst haben, aber achten Sie auf das Gehäuse! Möglicherweise ist Ihre Datenbankkollatierungseinstellung auf "SQL_Latin1_General_CP1_CS_AS" festgelegt. CS ist hier das Schlüsselwort. Es steht für "CaseSensitiv", daher muss Ihr Code mit dem Gehäuse übereinstimmen! Ein weiterer Punkt könnte sein, dass Ihr System MySql ist, als der Name date_add (). Grüße;)
Nightking
3
Diese Lösung wird vom Problem des Jahres 2038 betroffen sein, da für die Funktion dateadd ein int-Typ erforderlich ist. In der Dokumentation heißt es: "Das Zahlenargument darf den Bereich von int nicht überschreiten." docs.microsoft.com/en-us/sql/t-sql/functions/… en.wikipedia.org/wiki/Year_2038_problem
Patrick H
28

Wenn jemand unter Fehler kommt:

Arithmetischer Überlauffehler beim Konvertieren des Ausdrucks in den Datentyp int

Da der Unix-Zeitstempel in bigint (anstelle von int) ist, können Sie Folgendes verwenden:

SELECT DATEADD(S, CONVERT(int,LEFT(1462924862735870900, 10)), '1970-01-01')
FROM TABLE

Ersetzen Sie den fest codierten Zeitstempel für Ihre aktuelle Spalte durch einen Unix-Zeitstempel

Quelle: MSSQL bigint Unix-Zeitstempel zu Datetime mit Millisekunden

jmojico
quelle
In Millisekunden der Epoche sogar noch besser: SELECT DATEADD (ms, 1517270454852% 1000, DATEADD (S, 1517270454852/1000, '1970-01-01'))
G DeMasters
24

So was

Fügen Sie die Unix-Datumszeit (Epoche) in Sekunden zum Basisdatum hinzu

das wird es vorerst bekommen (2010-05-25 07: 56: 23.000)

 SELECT dateadd(s,1274756183,'19700101 05:00:00:000')

Wenn Sie rückwärts gehen möchten, schauen Sie sich dieses http://wiki.lessthandot.com/index.php/Epoch_Date an

SQLMenace
quelle
1
Warum 05:00:00 statt 00:00:00?
Svisstack
2
@Svisstack die 5 Stunden sind für Zeitzonenunterschied. 5:00:00 bedeutet, dass er GMT-5 Stunden ist
Jordy van Eijk
Klappt wunderbar. Wenn Sie sich an die Zeitzone anpassen müssen, dann tun Sie das auf jeden
Fall
7

Dies wird es tun:

declare @UNIX_TIME int
select @UNIX_TIME = 1111111111
-- Using dateadd to add seconds to 1970-01-01
select [Datetime from UNIX Time] = dateadd(!precision!,@UNIX_TIME,'1970-01-01')

Anstelle von! Präzision! Verwenden Sie: ss, ms oder mcs entsprechend der Genauigkeit des Zeitstempels. Bigint ist in der Lage, Mikrosekundengenauigkeit zu halten.

Ovidiu Pacurar
quelle
4

Wenn Sie n Sekunden 1970-01-01hinzufügen, erhalten Sie ein UTC-Datum, da n , der Unix-Zeitstempel, die Anzahl der Sekunden ist, die seit 00:00:00 UTC (Coordinated Universal Time), Donnerstag, 1. Januar 1970, vergangen sind .

In SQL Server 2016 können Sie mithilfe von eine Zeitzone in eine andere konvertieren AT TIME ZONE. Sie müssen nur den Namen der Zeitzone im Windows-Standardformat kennen:

SELECT *
FROM (VALUES (1514808000), (1527854400)) AS Tests(UnixTimestamp)
CROSS APPLY (SELECT DATEADD(SECOND, UnixTimestamp, '1970-01-01') AT TIME ZONE 'UTC') AS CA1(UTCDate)
CROSS APPLY (SELECT UTCDate AT TIME ZONE 'Pacific Standard Time') AS CA2(LocalDate)
| UnixTimestamp | UTCDate                    | LocalDate                  |
|---------------|----------------------------|----------------------------|
| 1514808000    | 2018-01-01 12:00:00 +00:00 | 2018-01-01 04:00:00 -08:00 |
| 1527854400    | 2018-06-01 12:00:00 +00:00 | 2018-06-01 05:00:00 -07:00 |

Oder einfach:

SELECT *, DATEADD(SECOND, UnixTimestamp, '1970-01-01') AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time'
FROM (VALUES (1514808000), (1527854400)) AS Tests(UnixTimestamp)
| UnixTimestamp | LocalDate                  |
|---------------|----------------------------|
| 1514808000    | 2018-01-01 04:00:00 -08:00 |
| 1527854400    | 2018-06-01 05:00:00 -07:00 |

Anmerkungen:

  • Sie können die Zeitzoneninformationen durch Casting DATETIMEOFFSETauf abhacken DATETIME.
  • Bei der Konvertierung wird die Sommerzeit berücksichtigt. Die pazifische Zeit war UTC-08: 00 im Januar 2018 und UTC-07: 00 im Juni 2018.
Salman A.
quelle
3

Wenn die Zeit in Millisekunden ist und man sie beibehalten muss:

DECLARE @value VARCHAR(32) = '1561487667713';

SELECT DATEADD(MILLISECOND, CAST(RIGHT(@value, 3) AS INT) - DATEDIFF(MILLISECOND,GETDATE(),GETUTCDATE()), DATEADD(SECOND, CAST(LEFT(@value, 10) AS INT), '1970-01-01T00:00:00'))
gotqn
quelle
1

Dies baut auf der Arbeit auf, die Daniel Little für diese Frage geleistet hat, berücksichtigt jedoch die Sommerzeit (funktioniert für Daten vom 01.01.1902 und höher aufgrund der int-Begrenzung der Dateadd-Funktion):

Wir müssen zuerst eine Tabelle erstellen, in der die Datumsbereiche für die Sommerzeit gespeichert werden (Quelle: Zeitverlauf in den USA ):

CREATE TABLE [dbo].[CFG_DAY_LIGHT_SAVINGS_TIME](
  [BEGIN_DATE] [datetime] NULL,
  [END_DATE] [datetime] NULL,
  [YEAR_DATE] [smallint] NULL
) ON [PRIMARY]

GO

INSERT INTO CFG_DAY_LIGHT_SAVINGS_TIME VALUES
('2001-04-01 02:00:00.000',   '2001-10-27 01:59:59.997',    2001),
('2002-04-07 02:00:00.000',   '2002-10-26 01:59:59.997',    2002),
('2003-04-06 02:00:00.000',   '2003-10-25 01:59:59.997',    2003),
('2004-04-04 02:00:00.000',   '2004-10-30 01:59:59.997',    2004),
('2005-04-03 02:00:00.000',   '2005-10-29 01:59:59.997',    2005),
('2006-04-02 02:00:00.000',   '2006-10-28 01:59:59.997',    2006),
('2007-03-11 02:00:00.000',   '2007-11-03 01:59:59.997',    2007),
('2008-03-09 02:00:00.000',   '2008-11-01 01:59:59.997',    2008),
('2009-03-08 02:00:00.000',   '2009-10-31 01:59:59.997',    2009),
('2010-03-14 02:00:00.000',   '2010-11-06 01:59:59.997',    2010),
('2011-03-13 02:00:00.000',   '2011-11-05 01:59:59.997',    2011),
('2012-03-11 02:00:00.000',   '2012-11-03 01:59:59.997',    2012),
('2013-03-10 02:00:00.000',   '2013-11-02 01:59:59.997',    2013),
('2014-03-09 02:00:00.000',   '2014-11-01 01:59:59.997',    2014),
('2015-03-08 02:00:00.000',   '2015-10-31 01:59:59.997',    2015),
('2016-03-13 02:00:00.000',   '2016-11-05 01:59:59.997',    2016),
('2017-03-12 02:00:00.000',   '2017-11-04 01:59:59.997',    2017),
('2018-03-11 02:00:00.000',   '2018-11-03 01:59:59.997',    2018),
('2019-03-10 02:00:00.000',   '2019-11-02 01:59:59.997',    2019),
('2020-03-08 02:00:00.000',   '2020-10-31 01:59:59.997',    2020),
('2021-03-14 02:00:00.000',   '2021-11-06 01:59:59.997',    2021),
('2022-03-13 02:00:00.000',   '2022-11-05 01:59:59.997',    2022),
('2023-03-12 02:00:00.000',   '2023-11-04 01:59:59.997',    2023),
('2024-03-10 02:00:00.000',   '2024-11-02 01:59:59.997',    2024),
('2025-03-09 02:00:00.000',   '2025-11-01 01:59:59.997',    2025),
('1967-04-30 02:00:00.000',   '1967-10-29 01:59:59.997',    1967),
('1968-04-28 02:00:00.000',   '1968-10-27 01:59:59.997',    1968),
('1969-04-27 02:00:00.000',   '1969-10-26 01:59:59.997',    1969),
('1970-04-26 02:00:00.000',   '1970-10-25 01:59:59.997',    1970),
('1971-04-25 02:00:00.000',   '1971-10-31 01:59:59.997',    1971),
('1972-04-30 02:00:00.000',   '1972-10-29 01:59:59.997',    1972),
('1973-04-29 02:00:00.000',   '1973-10-28 01:59:59.997',    1973),
('1974-01-06 02:00:00.000',   '1974-10-27 01:59:59.997',    1974),
('1975-02-23 02:00:00.000',   '1975-10-26 01:59:59.997',    1975),
('1976-04-25 02:00:00.000',   '1976-10-31 01:59:59.997',    1976),
('1977-04-24 02:00:00.000',   '1977-10-31 01:59:59.997',    1977),
('1978-04-30 02:00:00.000',   '1978-10-29 01:59:59.997',    1978),
('1979-04-29 02:00:00.000',   '1979-10-28 01:59:59.997',    1979),
('1980-04-27 02:00:00.000',   '1980-10-26 01:59:59.997',    1980),
('1981-04-26 02:00:00.000',   '1981-10-25 01:59:59.997',    1981),
('1982-04-25 02:00:00.000',   '1982-10-25 01:59:59.997',    1982),
('1983-04-24 02:00:00.000',   '1983-10-30 01:59:59.997',    1983),
('1984-04-29 02:00:00.000',   '1984-10-28 01:59:59.997',    1984),
('1985-04-28 02:00:00.000',   '1985-10-27 01:59:59.997',    1985),
('1986-04-27 02:00:00.000',   '1986-10-26 01:59:59.997',    1986),
('1987-04-05 02:00:00.000',   '1987-10-25 01:59:59.997',    1987),
('1988-04-03 02:00:00.000',   '1988-10-30 01:59:59.997',    1988),
('1989-04-02 02:00:00.000',   '1989-10-29 01:59:59.997',    1989),
('1990-04-01 02:00:00.000',   '1990-10-28 01:59:59.997',    1990),
('1991-04-07 02:00:00.000',   '1991-10-27 01:59:59.997',    1991),
('1992-04-05 02:00:00.000',   '1992-10-25 01:59:59.997',    1992),
('1993-04-04 02:00:00.000',   '1993-10-31 01:59:59.997',    1993),
('1994-04-03 02:00:00.000',   '1994-10-30 01:59:59.997',    1994),
('1995-04-02 02:00:00.000',   '1995-10-29 01:59:59.997',    1995),
('1996-04-07 02:00:00.000',   '1996-10-27 01:59:59.997',    1996),
('1997-04-06 02:00:00.000',   '1997-10-26 01:59:59.997',    1997),
('1998-04-05 02:00:00.000',   '1998-10-25 01:59:59.997',    1998),
('1999-04-04 02:00:00.000',   '1999-10-31 01:59:59.997',    1999),
('2000-04-02 02:00:00.000',   '2000-10-29 01:59:59.997',    2000)
GO

Jetzt erstellen wir eine Funktion für jede amerikanische Zeitzone. Dies setzt voraus, dass die Unix-Zeit in Millisekunden angegeben ist. Wenn es in Sekunden ist, entfernen Sie das / 1000 aus dem Code:

Pazifik

create function [dbo].[UnixTimeToPacific] 
 (@unixtime bigint)
   returns datetime
   as
   begin
     declare @pacificdatetime datetime
     declare @interimdatetime datetime = dateadd(s, @unixtime/1000, '1970-01-01')
     select  @pacificdatetime =  dateadd(hour,case when @interimdatetime between begin_date and end_date then -7 else -8 end  ,@interimdatetime)
     from cfg_day_light_savings_time  where  year_date = datepart(year,@interimdatetime)
     if @pacificdatetime is null 
       select @pacificdatetime= dateadd(hour, -7, @interimdatetime)
return @pacificdatetime    
end

Ost

create function [dbo].[UnixTimeToEastern] 
 (@unixtime bigint)
   returns datetime
   as
   begin
     declare @easterndatetime datetime
     declare @interimdatetime datetime = dateadd(s, @unixtime/1000, '1970-01-01')
     select  @easterndatetime =  dateadd(hour,case when @interimdatetime between begin_date and end_date then -4 else -5 end  ,@interimdatetime)
     from cfg_day_light_savings_time  where  year_date = datepart(year,@interimdatetime)
     if @easterndatetime is null 
       select @easterndatetime= dateadd(hour, -4, @interimdatetime)
return @easterndatetime    
end

Zentral

create function [dbo].[UnixTimeToCentral] 
 (@unixtime bigint)
   returns datetime
   as
   begin
     declare @centraldatetime datetime
     declare @interimdatetime datetime = dateadd(s, @unixtime/1000, '1970-01-01')
     select  @centraldatetime =  dateadd(hour,case when @interimdatetime between begin_date and end_date then -5 else -6 end  ,@interimdatetime)
     from cfg_day_light_savings_time  where  year_date = datepart(year,@interimdatetime)
     if @centraldatetime is null 
       select @centraldatetime= dateadd(hour, -5, @interimdatetime)
return @centraldatetime    
end

Berg

create function [dbo].[UnixTimeToMountain] 
 (@unixtime bigint)
   returns datetime
   as
   begin
     declare @mountaindatetime datetime
     declare @interimdatetime datetime = dateadd(s, @unixtime/1000, '1970-01-01')
     select  @mountaindatetime =  dateadd(hour,case when @interimdatetime between begin_date and end_date then -6 else -7 end  ,@interimdatetime)
     from cfg_day_light_savings_time  where  year_date = datepart(year,@interimdatetime)
     if @mountaindatetime is null 
       select @mountaindatetime= dateadd(hour, -6, @interimdatetime)
return @mountaindatetime    
end

Hawaii

create function [dbo].[UnixTimeToHawaii] 
 (@unixtime bigint)
   returns datetime
   as
   begin
     declare @hawaiidatetime datetime
     declare @interimdatetime datetime = dateadd(s, @unixtime/1000, '1970-01-01')
     select  @hawaiidatetime =  dateadd(hour,-10,@interimdatetime)
     from cfg_day_light_savings_time  where  year_date = datepart(year,@interimdatetime)

return @hawaiidatetime    
end

Arizona

create function [dbo].[UnixTimeToArizona] 
 (@unixtime bigint)
   returns datetime
   as
   begin
     declare @arizonadatetime datetime
     declare @interimdatetime datetime = dateadd(s, @unixtime/1000, '1970-01-01')
     select  @arizonadatetime =  dateadd(hour,-7,@interimdatetime)
     from cfg_day_light_savings_time  where  year_date = datepart(year,@interimdatetime)

return @arizonadatetime    
end

Alaska

create function [dbo].[UnixTimeToAlaska] 
 (@unixtime bigint)
   returns datetime
   as
   begin
     declare @alaskadatetime datetime
     declare @interimdatetime datetime = dateadd(s, @unixtime/1000, '1970-01-01')
     select  @alaskadatetime =  dateadd(hour,case when @interimdatetime between begin_date and end_date then -8 else -9 end  ,@interimdatetime)
     from cfg_day_light_savings_time  where  year_date = datepart(year,@interimdatetime)
     if @alaskadatetime is null 
       select @alaskadatetime= dateadd(hour, -8, @interimdatetime)
return @alaskadatetime    
end
Jymbo
quelle
1
//BIGINT UNIX TIMESTAMP CONVERSION upto Millisecond Accuracy
CREATE FUNCTION [dbo].[ConvertUnixTimestamp] (@Datetime [BIGINT]) RETURNS DATETIME
AS
BEGIN

    RETURN DATEADD(MILLISECOND, cast(@Datetime as bigint) % 1000, 
    DATEADD(SECOND, (cast(@Datetime as bigint) / 1000)%60, 
    DATEADD(MINUTE, ((cast(@Datetime as bigint) / 1000)/60)%60, 
    DATEADD(HOUR, ((cast(@Datetime as bigint) / 1000)/60)/60, '19700101'))))
END
user3450075
quelle
1

Ich musste mich auch diesem Problem stellen. Leider war keine der Antworten (hier und auf Dutzenden anderer Seiten) für mich zufriedenstellend, da ich aufgrund von 32-Bit-Ganzzahl-Casts irgendwo immer noch keine Daten über das Jahr 2038 hinaus erreichen kann.

Eine Lösung, die am Ende für mich funktioniert hat, war die Verwendung von floatVariablen, sodass ich mindestens ein maximales Datum von haben konnte 2262-04-11T23:47:16.854775849. Dies deckt zwar nicht die gesamte datetimeDomäne ab, ist jedoch für meine Anforderungen ausreichend und kann anderen helfen, die auf dasselbe Problem stoßen.

-- date variables
declare @ts bigint; -- 64 bit time stamp, 100ns precision
declare @d datetime2(7) = GETUTCDATE(); -- 'now'
-- select @d = '2262-04-11T23:47:16.854775849'; -- this would be the max date

-- constants:
declare @epoch datetime2(7) = cast('1970-01-01T00:00:00' as datetime2(7));
declare @epochdiff int = 25567; -- = days between 1900-01-01 and 1970-01-01
declare @ticksofday bigint = 864000000000; -- = (24*60*60*1000*1000*10)

-- helper variables:
declare @datepart float;
declare @timepart float;
declare @restored datetime2(7);

-- algorithm:
select @ts = DATEDIFF_BIG(NANOSECOND, @epoch, @d) / 100; -- 'now' in ticks according to unix epoch
select @timepart = (@ts % @ticksofday) / @ticksofday; -- extract time part and scale it to fractional part (i. e. 1 hour is 1/24th of a day)
select @datepart = (@ts - @timepart) / @ticksofday; -- extract date part and scale it to fractional part
select @restored = cast(@epochdiff + @datepart + @timepart as datetime); -- rebuild parts to a datetime value

-- query original datetime, intermediate timestamp and restored datetime for comparison
select
  @d original,
  @ts unix64,
  @restored restored
;

-- example result for max date:
-- +-----------------------------+-------------------+-----------------------------+
-- | original                    | unix64            | restored                    |
-- +-----------------------------+-------------------+-----------------------------+
-- | 2262-04-11 23:47:16.8547758 | 92233720368547758 | 2262-04-11 23:47:16.8533333 |
-- +-----------------------------+-------------------+-----------------------------+

Es sind einige Punkte zu beachten:

  • In meinem Fall ist eine Genauigkeit von 100 ns erforderlich, dies scheint jedoch die Standardauflösung für 64-Bit-Unix-Zeitstempel zu sein. Wenn Sie eine andere Auflösung verwenden, müssen Sie @ticksofdaydie erste Zeile des Algorithmus entsprechend anpassen .
  • Ich verwende andere Systeme, die Probleme mit Zeitzonen usw. haben, und ich fand, dass die beste Lösung für mich darin besteht, immer UTC zu verwenden. Für Ihre Bedürfnisse kann dies abweichen.
  • 1900-01-01ist das Ursprungsdatum für datetime2, ebenso wie die Epoche 1970-01-01für Unix-Zeitstempel.
  • floats hat mir geholfen, das Problem des Jahres 2038 und ganzzahlige Überläufe und dergleichen zu lösen. Beachten Sie jedoch, dass Gleitkommazahlen nicht sehr leistungsfähig sind und die Verarbeitung einer großen Anzahl von Zeitstempeln verlangsamen können. Floats können auch zu Rundungsverlusten aufgrund von Rundungsfehlern führen, wie Sie im Vergleich der Beispielergebnisse für das oben angegebene Maximaldatum sehen können (hier beträgt der Fehler etwa 1,4425 ms).
  • In der letzten Zeile des Algorithmus gibt es eine Umwandlung in datetime. Leider gibt es keine explizite Umwandlung von numerischen in datetime2zulässige Werte , aber es ist zulässig, numerische Werte datetimeexplizit umzuwandeln, und dies wird wiederum implizit in umgewandelt datetime2. Dies mag vorerst richtig sein, kann sich jedoch in zukünftigen Versionen von SQL Server ändern: Entweder wird eine dateadd_big()Funktion vorhanden sein oder die explizite Umwandlung datetime2wird zugelassen oder die explizite Umwandlung datetimewird nicht zugelassen, sodass dies entweder unterbrochen werden kann oder eintreten kann eines Tages ein einfacher Weg.
Chris Tophski
quelle
1

Für GMT ist hier der einfachste Weg:

Select dateadd(s, @UnixTime+DATEDIFF (S, GETUTCDATE(), GETDATE()), '1970-01-01')
Saolin
quelle
0

Besser? Diese Funktion konvertiert Unixtime in Millisekunden in Datum / Uhrzeit. Es ist Millisekunden verloren gegangen, aber immer noch sehr nützlich zum Filtern.

CREATE FUNCTION [dbo].[UnixTimestampToGMTDatetime] 
(@UnixTimestamp bigint)
RETURNS datetime
AS
BEGIN
       DECLARE @GMTDatetime datetime
       select @GMTDatetime = 
       CASE
       WHEN dateadd(ss, @UnixTimestamp/1000, '1970-01-01') 
       BETWEEN 
           Convert(DATETIME, Convert(VARCHAR(4), Year(dateadd(ss, @UnixTimestamp/1000, '1970-01-01') )) + '-03-' + Convert(VARCHAR(2), (31 - (5 * Year(dateadd(ss, @UnixTimestamp/1000, '1970-01-01') )/4 + 4) % 7)) + ' 01:00:00', 20)
       AND
           Convert(DATETIME, Convert(VARCHAR(4), Year(dateadd(ss, @UnixTimestamp/1000, '1970-01-01') )) + '-10-' + Convert(VARCHAR(2), (31 - (5 * Year(dateadd(ss, @UnixTimestamp/1000, '1970-01-01') )/4 + 1) % 7)) + ' 02:00:00', 20)
       THEN Dateadd(hh, 1, dateadd(ss, @UnixTimestamp/1000, '1970-01-01'))
       ELSE Dateadd(hh, 0, dateadd(ss, @UnixTimestamp/1000, '1970-01-01'))
       END
RETURN @GMTDatetime    
END
MtAt
quelle
0

Die Lösung kann folgende sein:

DECLARE @UnixTimeStamp bigint = 1564646400000 /*2019-08-01 11:00 AM*/

DECLARE @LocalTimeOffset bigint = DATEDIFF(MILLISECOND, GETDATE(), GETUTCDATE());
DECLARE @AdjustedTimeStamp bigint = @UnixTimeStamp - @LocalTimeOffset;
SELECT [DateTime] = DATEADD(SECOND, @AdjustedTimeStamp % 1000, DATEADD(SECOND, @AdjustedTimeStamp / 1000, '19700101'));
Vitaly Ilyuhin
quelle
0

@DanielLittle hat die einfachste und eleganteste Antwort auf die spezifische Frage. Wenn Sie jedoch an einer Konvertierung in eine bestimmte Zeitzone UND unter Berücksichtigung der Sommerzeit interessiert sind, funktioniert Folgendes gut:

CAST(DATEADD(S, [UnixTimestamp], '1970-01-01') AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time' AS Datetime)

Hinweis: Diese Lösung funktioniert nur unter SQL Server 2016 und höher (und Azure).

So erstellen Sie eine Funktion:

CREATE FUNCTION dbo.ConvertUnixTime (@input INT)
RETURNS Datetime
AS BEGIN
    DECLARE @Unix Datetime

    SET @Unix = CAST(DATEADD(S, @Input, '1970-01-01') AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time' AS Datetime)

    RETURN @Unix
END

Sie können die Funktion folgendermaßen aufrufen:

SELECT   dbo.ConvertUnixTime([UnixTimestamp])
FROM     YourTable
Kenny
quelle