Comment puis-je convertir bigint (horodatage UNIX) en datetime dans SQL Server?

Réponses:

58

essayer:

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.
la source
2
+1 Pour la conversion UTC-> locale. Notez que l'heure d'été / d'hiver sera toujours désactivée si vous essayez de traduire le 10 juin en février.
Andomar
11
-1 pour la conversion locale UTC->. Il ne gère pas correctement l'heure d'été. Pour moi, c'est une erreur.
Pavel Horal
+1 pour la solution créative! Fonctionne très bien. Pour info, il y a une erreur de syntaxe dans le SQL. Le point-virgule à la fin de la première ligne "DECLARE" doit être supprimé car une virgule suit.
Seth le
2
Ça ne marche pas pour moi. Je suis en train de l'essayer avec 1517270400000 et j'obtiens cette erreur: Erreur de dépassement arithmétique lors de la conversion de l'expression en type de données int.
danois
1
Il y avait aussi un débordement, signifiant normalement que des millisecondes sont impliquées, résolu simplement comme: sélectionnez dbo.fn_ConvertToDateTime (src_column / 1000) à partir de src_table;
access_granted
304

Cela a fonctionné pour moi:

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

Au cas où quelqu'un se demanderait pourquoi 1970-01-01, cela s'appelle le temps d'époque .

Voici une citation de Wikipedia:

Le nombre de secondes qui se sont écoulées depuis 00:00:00 temps universel coordonné (UTC), jeudi 1er janvier 1970, [1] [note 1] sans compter les secondes intercalaires.

Daniel Little
la source
17
Cela doit être marqué comme correct. J'aimerais pouvoir voter pour cette réponse à chaque fois que
j'atterris
2
@BenDundee Je suis vraiment d'accord avec vous. Quelle solution élégante. J'ai cherché partout une formule et j'ai finalement opté pour une formule pour devoir recommencer la recherche lorsque j'ai commencé à rencontrer des erreurs une semaine plus tard. Heureusement, j'ai trouvé celui-ci lors de la deuxième remise des gaz.
déséquilibré
1
J'utilise cette solution. Cette date formatée était concaténée avec d'autres données, j'avais donc un varchar ... Facile! Pas besoin de prendre la peine de formater ces journaux dans l'application. Cependant, des problèmes de fuseau horaire sauvages sont apparus! Mes dates utilisaient le fuseau horaire UTC au lieu du fuseau horaire du client :(
gustavohenke
2
@Whitecat Je ne sais pas si vous avez déjà résolu votre problème, mais surveillez le boîtier! Peut-être que le paramètre de classement de votre base de données est défini sur quelque chose comme «SQL_Latin1_General_CP1_CS_AS», CS est le mot-clé ici. Il signifie "CaseSensitiv" donc votre code doit correspondre au boîtier! Un autre point pourrait être que votre système est MySql, que le nom est date_add (). Cordialement;)
Nightking
3
Cette solution sera affectée par le problème de l'année 2038 car la fonction dateadd nécessite un type int. La documentation dit "L'argument nombre ne peut pas dépasser la plage de int." docs.microsoft.com/en-us/sql/t-sql/functions/… en.wikipedia.org/wiki/Year_2038_problem
Patrick H
30

Si quelqu'un obtient une erreur ci-dessous:

Erreur de dépassement arithmétique lors de la conversion de l'expression en type de données int

en raison du fait que l'horodatage unix est en bigint (au lieu de int), vous pouvez utiliser ceci:

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

Remplacez l'horodatage codé en dur de votre colonne réelle par un horodatage unix

Source: MSSQL bigint Unix Timestamp à Datetime en millisecondes

jmojico
la source
Compte tenu des millisecondes d'époque, encore mieux: SELECT DATEADD (ms, 1517270454852% 1000, DATEADD (S, 1517270454852/1000, '1970-01-01'))
G DeMasters
25

Comme ça

ajouter la date / heure Unix (epoch) à la date de base en secondes

cela l'aura pour le moment (2010-05-25 07: 56: 23.000)

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

Si vous voulez faire marche arrière, jetez un œil à ce http://wiki.lessthandot.com/index.php/Epoch_Date

SQLMenace
la source
1
pourquoi 05:00:00 au lieu de 00:00:00?
Svisstack
2
@Svisstack les 5 heures correspondent au décalage horaire. 5:00:00 signifie qu'il est GMT-5 heures
Jordy van Eijk
Fonctionne comme un charme. Si vous avez besoin d'ajuster le fuseau horaire, alors faites-le certainement, mais considérez cela très efficace
clifton_h
7

Cela le fera:

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')

Au lieu de! Précision! utiliser: ss, ms ou mcs selon la précision de l'horodatage. Bigint est capable de maintenir une précision de l'ordre de la microseconde.

Ovidiu Pacurar
la source
4

Ajouter n secondes à 1970-01-01vous donnera une date UTC car n , l'horodatage Unix, est le nombre de secondes qui se sont écoulées depuis 00:00:00 UTC (temps universel coordonné), jeudi 1er janvier 1970 .

Dans SQL Server 2016, vous pouvez convertir un fuseau horaire en un autre à l'aide de AT TIME ZONE. Il vous suffit de connaître le nom du fuseau horaire au format standard Windows:

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 |

Ou simplement:

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 |

Remarques:

  • Vous pouvez couper les informations du fuseau horaire en diffusant DATETIMEOFFSETsur DATETIME.
  • La conversion prend en compte l'heure d'été. L'heure du Pacifique était UTC-08: 00 en janvier 2018 et UTC-07: 00 en juin 2018.
Salman A
la source
3

Si le temps est en millisecondes et qu'il faut les conserver:

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
la source
1

Ceci s'appuie sur le travail que Daniel Little a fait pour cette question, mais en tenant compte de l'heure d'été (fonctionne pour les dates 01-01 1902 et plus en raison de la limite int sur la fonction dateadd):

Nous devons d'abord créer un tableau qui stockera les plages de dates pour l'heure d'été (source: History of time aux États-Unis ):

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

Nous créons maintenant une fonction pour chaque fuseau horaire américain. Cela suppose que l'heure Unix est en millisecondes. Si c'est en secondes, supprimez le / 1000 du code:

Pacifique

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

Est

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

Central

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

Montagne

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
la source
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
la source
1

J'ai dû faire face à ce problème aussi. Malheureusement, aucune des réponses (ici et dans des dizaines d'autres pages) n'a été satisfaisante pour moi, car je ne peux toujours pas atteindre les dates au-delà de l'année 2038 en raison de cast entiers 32 bits quelque part.

Une solution qui a fonctionné pour moi à la fin a été d'utiliser des floatvariables, afin que je puisse avoir au moins une date maximale de 2262-04-11T23:47:16.854775849. Pourtant, cela ne couvre pas tout le datetimedomaine, mais cela suffit à mes besoins et peut aider d'autres personnes rencontrant le même problème.

-- 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 |
-- +-----------------------------+-------------------+-----------------------------+

Il y a quelques points à considérer:

  • Une précision de 100ns est la condition requise dans mon cas, mais cela semble être la résolution standard pour les horodatages unix 64 bits. Si vous utilisez une autre résolution, vous devez ajuster @ticksofdayla première ligne de l'algorithme en conséquence.
  • J'utilise d'autres systèmes qui ont leurs problèmes avec les fuseaux horaires, etc. et j'ai trouvé que la meilleure solution pour moi serait toujours d'utiliser UTC. Pour vos besoins, cela peut différer.
  • 1900-01-01est la date d'origine pour datetime2, tout comme l'époque 1970-01-01pour les horodatages Unix.
  • floats m'a aidé à résoudre le problème de l'année 2038 et les débordements d'entiers et autres, mais gardez à l'esprit que les nombres à virgule flottante ne sont pas très performants et peuvent ralentir le traitement d'un grand nombre d'horodatages. De plus, les flottants peuvent entraîner une perte de précision en raison d'erreurs d'arrondi, comme vous pouvez le voir dans la comparaison des résultats d'exemple pour la date maximale ci-dessus (ici, l'erreur est d'environ 1,4425 ms).
  • Dans la dernière ligne de l'algorithme, il y a un cast vers datetime. Malheureusement, il n'y a pas de datetime2conversion datetimeexplicite des valeurs numériques en valeurs autorisées, mais il est autorisé de convertir les valeurs numériques explicitement et cela, à son tour, est converti implicitement en datetime2. Cela peut être correct, pour le moment, mais peut changer dans les versions futures de SQL Server: Soit il y aura une dateadd_big()fonction, soit la conversion explicite en datetime2sera autorisée ou la distribution explicite en datetimesera interdite, donc cela peut être interrompu ou il peut arriver un moyen plus facile un jour.
Chris Tophski
la source
1

Pour GMT, voici le moyen le plus simple:

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

Mieux? Cette fonction convertit unixtime en millisecondes en datetime. Il a perdu des millisecondes, mais reste très utile pour le filtrage.

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
la source
0

La solution peut être la suivante:

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
la source
0

@DanielLittle a la réponse la plus simple et la plus élégante à la question spécifique. Cependant, si vous êtes intéressé par la conversion vers un fuseau horaire spécifique ET en tenant compte de l'heure d'été (heure d'été), ce qui suit fonctionne bien:

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

Remarque: cette solution fonctionne uniquement sur SQL Server 2016 et versions ultérieures (et Azure).

Pour créer une fonction:

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

Vous pouvez appeler la fonction comme ceci:

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