Làm cách nào để chuyển đổi bigint (dấu thời gian UNIX) thành datetime trong SQL Server?


Câu trả lời:


57

thử:

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

2
+1 Đối với UTC-> chuyển đổi cục bộ. Lưu ý rằng mùa hè / mùa đông vẫn sẽ tắt nếu bạn cố gắng dịch vào ngày 10 tháng 6 trong tháng 2.
Andomar

11
-1 cho UTC-> chuyển đổi cục bộ. Đó là không chính xác xử lý thời gian tiết kiệm ánh sáng ban ngày. Đối với tôi, điều này là sai lầm.
Pavel Horal

+1 cho giải pháp sáng tạo! Hoạt động tuyệt vời. FYI, có lỗi cú pháp trong SQL. Dấu chấm phẩy ở cuối dòng "DECLARE" đầu tiên cần phải được xóa vì dấu phẩy theo sau.
Seth

2
Nó không hiệu quả với tôi. Tôi đang thử nó với 1517270400000 và gặp lỗi này: Lỗi tràn số học khi chuyển đổi biểu thức thành kiểu dữ liệu int.
Tiếng Đan Mạch

1
Cũng nhận được tràn, thông thường có nghĩa là có liên quan đến mili giây, được giải quyết đơn giản như: select dbo.fn_ConvertToDateTime (src_column / 1000) từ src_table;
access_granted

304

Điều này đã làm việc cho tôi:

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

Trong trường hợp bất kỳ ai thắc mắc tại sao 1970-01-01, Đây được gọi là thời gian Kỷ nguyên .

Dưới đây là trích dẫn từ Wikipedia:

Số giây đã trôi qua kể từ 00:00:00 Giờ Phối hợp Quốc tế (UTC), Thứ Năm, ngày 1 tháng 1 năm 1970, [1] [ghi chú 1] không tính giây nhuận.


17
Điều này phải được đánh dấu là đúng. Tôi ước gì tôi có thể
ủng hộ

2
@BenDundee Tôi thực sự đồng ý với bạn. Thật là một giải pháp thanh lịch. Tôi đã tìm khắp nơi để tìm một công thức và cuối cùng chỉ tìm được một công thức duy nhất là phải đi tìm kiếm lại khi tôi bắt đầu gặp lỗi một tuần sau đó. Rất may, tôi đã tìm thấy cái này trong lần quay thứ hai.
Lopsided

1
Tôi đã được sử dụng giải pháp này. Ngày được định dạng này được nối với dữ liệu khác, vì vậy tôi có một varchar ... Dễ dàng! Không cần phải bận tâm để định dạng các bản ghi đó trong ứng dụng. Tuy nhiên, một số vấn đề về múi giờ hoang dã đã xuất hiện! Ngày của tôi sử dụng múi giờ UTC thay vì múi giờ của khách hàng :(
gustavohenke

2
@Whitecat Không biết bạn đã giải quyết được vấn đề của mình chưa, nhưng hãy xem cách viết hoa! Có thể cài đặt đối chiếu cơ sở dữ liệu của bạn được đặt thành một thứ gì đó giống như 'SQL_Latin1_General_CP1_CS_AS', CS là từ khóa ở đây. Nó là viết tắt của "CaseSensitiv" vì mã của bạn phải khớp với cách viết hoa! Một điểm khác có thể là Hệ thống của bạn là MySql, chứ không phải tên là date_add (). Trân trọng;)
Nightking

3
Giải pháp này sẽ bị ảnh hưởng bởi sự cố năm 2038 vì hàm dateadd yêu cầu kiểu int. Tài liệu cho biết "Đối số number không được vượt quá phạm vi int." docs.microsoft.com/en-us/sql/t-sql/functions/… en.wikipedia.org/wiki/Year_2038_problem
Patrick H

30

Nếu bất kỳ ai gặp lỗi dưới đây:

Lỗi tràn số học khi chuyển đổi biểu thức thành kiểu dữ liệu int

do dấu thời gian unix nằm trong bigint (thay vì int), bạn có thể sử dụng điều này:

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

Thay thế dấu thời gian được mã hóa cứng cho cột thực của bạn bằng dấu thời gian unix

Nguồn: MSSQL bigint Unix Timestamp thành Datetime với mili giây


Với phần nghìn mili giây, thậm chí còn tốt hơn: SELECT DATEADD (mili giây, 1517270454852% 1000, DATEADD (S, 1517270454852/1000, '1970-01-01'))
G DeMasters

25

Như thế này

thêm ngày giờ Unix (epoch) vào ngày cơ sở tính bằng giây

điều này sẽ có được nó ngay bây giờ (2010-05-25 07: 56: 23.000)

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

Nếu bạn muốn đảo ngược, hãy xem http://wiki.lessthandot.com/index.php/Epoch_Date này


1
tại sao lại là 05:00:00 thay vì 00:00:00?
Svisstack

2
@Svisstack 5 giờ là chênh lệch múi giờ. 5:00:00 nghĩa là anh ấy GMT-5 giờ
Jordy van Eijk

Hoạt động như một sự quyến rũ. Nếu bạn cần phải điều chỉnh cho múi giờ, sau đó chắc chắn làm điều đó nhưng xem xét việc này rất hiệu quả
clifton_h

7

Điều này sẽ làm điều đó:

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

Thay vì! Độ chính xác! sử dụng: ss, ms hoặc mcs theo độ chính xác của dấu thời gian. Bigint có khả năng giữ độ chính xác đến từng micro giây.



4

Thêm n giây vào 1970-01-01sẽ cung cấp cho bạn ngày UTCn , dấu thời gian Unix, là số giây đã trôi qua kể từ 00:00:00 Giờ Phối hợp Quốc tế (UTC), Thứ Năm, ngày 1 tháng 1 năm 1970 .

Trong SQL Server 2016, bạn có thể chuyển đổi múi giờ này sang múi giờ khác bằng cách sử dụng AT TIME ZONE. Bạn chỉ cần biết tên của múi giờ ở định dạng chuẩn của 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 |

Hoặc đơn giản:

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 |

Ghi chú:

  • Bạn có thể cắt thông tin múi giờ bằng cách truyền DATETIMEOFFSETđến DATETIME.
  • Việc chuyển đổi có tính đến thời gian tiết kiệm ánh sáng ban ngày. Giờ Thái Bình Dương là UTC-08: 00 vào tháng 1 năm 2018 và UTC-07: 00 vào tháng 6 năm 2018.

3

Nếu thời gian tính bằng mili giây và người ta cần bảo toàn chúng:

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

1

Điều này dựa trên công việc mà Daniel Little đã làm cho câu hỏi này, nhưng có tính đến thời gian tiết kiệm ánh sáng ban ngày (hoạt động cho các ngày 01-01 1902 trở lên do giới hạn int trên hàm dateadd):

Trước tiên, chúng tôi cần tạo một bảng sẽ lưu trữ phạm vi ngày cho giờ tiết kiệm ánh sáng ban ngày (nguồn: Lịch sử thời gian ở Hoa Kỳ ):

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

Bây giờ chúng tôi tạo một chức năng cho từng múi giờ của Mỹ. Điều này giả sử thời gian unix tính bằng mili giây. Nếu chỉ tính bằng giây, hãy xóa / 1000 khỏi mã:

Thái bình dương

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

phương Đông

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

Trung tâm

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

núi

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

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

1

Tôi cũng phải đối mặt với vấn đề này. Thật không may, không có câu trả lời nào (ở đây và trong hàng chục trang khác) thỏa mãn tôi, vì tôi vẫn không thể đạt được ngày sau năm 2038 do phôi số nguyên 32 bit ở đâu đó.

Cuối cùng, một giải pháp đã hiệu quả với tôi là sử dụng floatcác biến, vì vậy tôi có thể có ít nhất một ngày tối đa là 2262-04-11T23:47:16.854775849. Tuy nhiên, điều này không bao gồm toàn bộ datetimemiền, nhưng nó đủ cho nhu cầu của tôi và có thể giúp những người khác gặp phải vấn đề tương tự.

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

Có một số điểm cần xem xét:

  • Độ chính xác 100ns là yêu cầu trong trường hợp của tôi, tuy nhiên đây có vẻ là độ phân giải tiêu chuẩn cho dấu thời gian 64 bit unix. Nếu bạn sử dụng bất kỳ độ phân giải nào khác, bạn phải điều chỉnh @ticksofdayvà dòng đầu tiên của thuật toán cho phù hợp.
  • Tôi đang sử dụng các hệ thống khác có vấn đề với múi giờ, v.v. và tôi thấy giải pháp tốt nhất cho mình là luôn sử dụng UTC. Đối với nhu cầu của bạn, điều này có thể khác.
  • 1900-01-01là ngày xuất phát datetime2, cũng giống như kỷ nguyên 1970-01-01cho dấu thời gian unix.
  • floats đã giúp tôi giải quyết vấn đề năm 2038 và tràn số nguyên và tương tự, nhưng hãy nhớ rằng số dấu phẩy động không hiệu quả lắm và có thể làm chậm quá trình xử lý một lượng lớn dấu thời gian. Ngoài ra, float có thể dẫn đến mất độ chính xác do lỗi làm tròn, như bạn có thể thấy trong phần so sánh kết quả ví dụ cho ngày tối đa ở trên (ở đây, sai số là khoảng 1,4425ms).
  • Trong dòng cuối cùng của thuật toán có một phép ép kiểu datetime. Thật không may, không có phép ép kiểu rõ ràng nào từ giá trị số thành datetime2được phép, nhưng nó được phép ép kiểu số thành datetimemột cách rõ ràng và điều này, đến lượt nó, được ép kiểu ngầm định datetime2. Điều này có thể đúng, hiện tại, nhưng có thể thay đổi trong các phiên bản tương lai của SQL Server: Sẽ có một dateadd_big()hàm hoặc truyền rõ ràng datetime2sẽ được cho phép hoặc truyền rõ ràng datetimesẽ không được phép, vì vậy điều này có thể bị hỏng hoặc có thể xảy ra một cách dễ dàng hơn vào một ngày nào đó.

1

Đối với GMT, đây là cách dễ nhất:

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

0

Tốt hơn? Hàm này chuyển đổi unixtime tính bằng mili giây thành datetime. Nó bị mất phần nghìn giây, nhưng vẫn rất hữu ích để lọc.

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

0

Giải pháp có thể như sau:

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

0

@DanielLittle có câu trả lời dễ dàng và thanh lịch nhất cho câu hỏi cụ thể. Tuy nhiên, nếu bạn quan tâm đến việc chuyển đổi sang một múi giờ cụ thể VÀ có tính đến DST (Giờ tiết kiệm ánh sáng ban ngày), những cách sau hoạt động tốt:

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

Lưu ý: Giải pháp này chỉ hoạt động trên SQL Server 2016 trở lên (và Azure).

Để tạo một hàm:

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

Bạn có thể gọi hàm như sau:

SELECT   dbo.ConvertUnixTime([UnixTimestamp])
FROM     YourTable
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.