¿Cómo puedo convertir bigint (marca de tiempo UNIX) a fecha y hora en SQL Server?

Respuestas:

58

tratar:

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.
fuente
2
+1 Para la conversión UTC-> local. Tenga en cuenta que el verano / invierno seguirá estando desactivado si intenta traducir el 10 de junio durante febrero.
Andomar
11
-1 para la conversión UTC-> local. No está manejando correctamente el horario de verano. Para mí, esto es un error.
Pavel Horal
+1 para la solución creativa! Funciona genial. FYI, hay un error de sintaxis en el SQL. El punto y coma al final de la primera línea "DECLARE" debe eliminarse ya que sigue una coma.
Set
2
No funciona para mi. Lo estoy intentando con 1517270400000 y obtengo este error: Error de desbordamiento aritmético al convertir la expresión al tipo de datos int.
Danés
1
También estaba obteniendo un desbordamiento, lo que normalmente significa que hay milisegundos involucrados, resuelto simplemente como: seleccione dbo.fn_ConvertToDateTime (src_column / 1000) de src_table;
access_granted
304

Esto funcionó para mí:

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

En caso de que alguien se pregunte por qué 1970-01-01, esto se llama Época .

A continuación se muestra una cita de Wikipedia:

El número de segundos que han transcurrido desde las 00:00:00 hora universal coordinada (UTC), jueves 1 de enero de 1970, [1] [nota 1] sin contar los segundos intercalares.

Daniel pequeño
fuente
17
Esto debe marcarse como correcto. Me gustaría poder votar esta respuesta nuevamente cada vez que
aterrizo
2
@BenDundee Estoy realmente de acuerdo contigo. Qué elegante solución. Busqué una fórmula por todas partes y finalmente me decidí por una, solo para tener que volver a buscar cuando comencé a encontrar errores una semana después. Afortunadamente encontré este en la segunda vuelta.
Torcido
1
He estado usando esta solución. Esta fecha formateada fue concatenada con otros datos, así que tuve un varchar ... ¡Fácil! No es necesario que se moleste en formatear esos registros en la aplicación. Sin embargo, ¡aparecieron algunos problemas de zona horaria salvaje! Mis fechas usaban la zona horaria UTC en lugar de la zona horaria del cliente :(
gustavohenke
2
@Whitecat No sé si ya resolvió su problema, ¡pero cuidado con la carcasa! Tal vez la configuración de intercalación de su base de datos esté establecida en algo como 'SQL_Latin1_General_CP1_CS_AS', CS es la palabra clave aquí. Significa "CaseSensitiv", por lo que su código debe coincidir con la carcasa. Otro punto podría ser que su sistema es MySql, que el nombre es date_add (). Saludos;)
Nightking
3
Esta solución se verá afectada por el problema del año 2038 porque la función dateadd requiere un tipo int. La documentación dice "El argumento de número no puede exceder el rango de int". docs.microsoft.com/en-us/sql/t-sql/functions/… en.wikipedia.org/wiki/Year_2038_problem
Patrick H
30

Si alguien recibe un error a continuación:

Error de desbordamiento aritmético al convertir la expresión al tipo de datos int

debido a que la marca de tiempo de Unix está en bigint (en lugar de int), puede usar esto:

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

Reemplace la marca de tiempo codificada para su columna real con unix-timestamp

Fuente: MSSQL bigint Unix Timestamp a Datetime con milisegundos

jmojico
fuente
Dados milisegundos de época, incluso mejor: SELECT DATEADD (ms, 1517270454852% 1000, DATEADD (S, 1517270454852/1000, '1970-01-01'))
G DeMasters
25

Me gusta esto

agregue la fecha y hora de Unix (época) a la fecha base en segundos

esto lo conseguirá por ahora (2010-05-25 07: 56: 23.000)

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

Si desea retroceder, eche un vistazo a este http://wiki.lessthandot.com/index.php/Epoch_Date

SQLMenace
fuente
1
¿Por qué 05:00:00 en lugar de 00:00:00?
Svisstack
2
@Svisstack las 5 horas son por diferencia de zona horaria. 5:00:00 significa que es GMT-5 horas
Jordy van Eijk
Funciona de maravilla. Si necesita ajustarse a la zona horaria, entonces hágalo, pero considérelo muy eficiente
clifton_h
7

Esto lo hará:

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

En lugar de! Precisión! use: ss, ms o mcs según la precisión de la marca de tiempo. Bigint es capaz de mantener una precisión de microsegundos.

Ovidiu Pacurar
fuente
4

Agregar n segundos a 1970-01-01le dará una fecha UTC porque n , la marca de tiempo de Unix, es la cantidad de segundos que han transcurrido desde las 00:00:00 de la hora universal coordinada (UTC), el jueves 1 de enero de 1970 .

En SQL Server 2016, puede convertir una zona horaria a otra usando AT TIME ZONE. Solo necesita saber el nombre de la zona horaria en formato estándar de 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 |

O simplemente:

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 |

Notas:

  • Puede cortar la información de la zona horaria enviando DATETIMEOFFSETaDATETIME .
  • La conversión tiene en cuenta el horario de verano. La hora del Pacífico fue UTC-08: 00 en enero de 2018 y UTC-07: 00 en junio de 2018.
Salman A
fuente
3

Si el tiempo está en milisegundos y es necesario preservarlos:

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
fuente
1

Esto se basa en el trabajo que hizo Daniel Little para esta pregunta, pero teniendo en cuenta el horario de verano (funciona para las fechas 01-01 1902 y superiores debido al límite int en la función dateadd):

Primero necesitamos crear una tabla que almacene los rangos de fechas para el horario de verano (fuente: Historia del tiempo en los Estados Unidos ):

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

Ahora creamos una función para cada zona horaria estadounidense. Esto supone que el tiempo de Unix está en milisegundos. Si es en segundos, elimine el / 1000 del código:

Pacífico

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

Oriental

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

Montaña

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

Hawai

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
fuente
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
fuente
1

Yo también tuve que enfrentarme a este problema. Desafortunadamente, ninguna de las respuestas (aquí y en docenas de otras páginas) ha sido satisfactoria para mí, ya que todavía no puedo alcanzar fechas más allá del año 2038 debido a conversiones de enteros de 32 bits en alguna parte.

Una solución que funcionó para mí al final fue usar floatvariables, por lo que podría tener al menos una fecha máxima de 2262-04-11T23:47:16.854775849. Aún así, esto no cubre todo el datetimedominio, pero es suficiente para mis necesidades y puede ayudar a otros a encontrar el mismo problema.

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

Hay algunos puntos a considerar:

  • La precisión de 100ns es el requisito en mi caso, sin embargo, esta parece ser la resolución estándar para marcas de tiempo Unix de 64 bits. Si usa cualquier otra resolución, debe ajustar @ticksofdayy la primera línea del algoritmo en consecuencia.
  • Estoy usando otros sistemas que tienen sus problemas con las zonas horarias, etc. y encontré que la mejor solución para mí sería siempre usar UTC. Para sus necesidades, esto puede variar.
  • 1900-01-01es la fecha de origen datetime2, al igual que la época 1970-01-01de las marcas de tiempo de Unix.
  • floats me ayudó a resolver el problema del año 2038 y los desbordamientos de enteros y demás, pero tenga en cuenta que los números de punto flotante no funcionan muy bien y pueden ralentizar el procesamiento de una gran cantidad de marcas de tiempo. Además, los flotadores pueden provocar una pérdida de precisión debido a errores de redondeo, como puede ver en la comparación de los resultados del ejemplo para la fecha máxima anterior (aquí, el error es de aproximadamente 1,4425 ms).
  • En la última línea del algoritmo hay una conversión a datetime. Desafortunadamente, no hay una datetime2conversión datetimeexplícita de valores numéricos a permitidos, pero está permitido convertir números a explícitamente y esto, a su vez, se convierte implícitamente en datetime2. Esto puede ser correcto, por ahora, pero puede cambiar en futuras versiones de SQL Server: o habrá una dateadd_big()función o datetime2se permitirá la conversión explícita a datetime, o la conversión explícita a no se permitirá, por lo que esto puede romperse o puede ocurrir. una forma más fácil algún día.
Chris Tophski
fuente
1

Para GMT, esta es la forma más sencilla:

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

¿Mejor? Esta función convierte unixtime en milisegundos a datetime. Se han perdido milisegundos, pero sigue siendo muy útil para filtrar.

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
fuente
0

La solución puede ser la siguiente:

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
fuente
0

@DanielLittle tiene la respuesta más fácil y elegante a la pregunta específica. Sin embargo, si está interesado en realizar la conversión a una zona horaria específica Y teniendo en cuenta el horario de verano (DST), lo siguiente funciona bien:

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

Nota: esta solución solo funciona en SQL Server 2016 y versiones posteriores (y Azure).

Para crear una función:

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

Puedes llamar a la función así:

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