Bagaimana cara mengonversi bigint (stempel waktu UNIX) ke datetime di SQL Server?

Jawaban:

57

mencoba:

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.
sumber
2
+1 Untuk UTC-> konversi lokal. Perhatikan bahwa musim panas / musim dingin masih tidak aktif jika Anda mencoba menerjemahkan 10 Juni selama Februari.
Andomar
11
-1 untuk UTC-> konversi lokal. Ini tidak menangani waktu musim panas dengan benar. Bagi saya, ini menyesatkan.
Pavel Horal
1 untuk solusi kreatif! Bekerja dengan baik. FYI, ada kesalahan sintaks di SQL. Titik koma di akhir baris pertama "MENYATAKAN" perlu dihilangkan karena koma mengikuti.
Seth
2
Itu tidak berhasil untuk saya. Saya mencobanya dengan 1517270400000 dan mendapatkan kesalahan ini: Kesalahan overflow aritmatika mengubah ekspresi menjadi tipe data int.
Denmark
1
Juga mendapatkan overflow, biasanya berarti bahwa milidetik terlibat, diselesaikan hanya sebagai: pilih dbo.fn_ConvertToDateTime (src_column / 1000) dari src_table;
access_granted
304

Ini berhasil untuk saya:

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

Jika ada yang bertanya-tanya mengapa 1970-01-01, ini disebut waktu Epoch .

Di bawah ini adalah kutipan dari Wikipedia:

Jumlah detik yang telah berlalu sejak 00:00:00 Waktu Universal Terkoordinasi (UTC), Kamis, 1 Januari 1970, [1] [catatan 1] tidak termasuk detik kabisat.

Daniel Little
sumber
17
Ini harus ditandai sebagai benar. Saya berharap saya dapat meningkatkan jawaban ini lagi setiap kali saya mendarat di sini :)
BenDundee
2
@ BenDundee Saya sangat setuju dengan Anda. Solusi yang sangat elegan. Saya mencari-cari formula ke seluruh penjuru dan akhirnya memilih satu hanya untuk harus mencari lagi ketika saya mulai mengalami kesalahan seminggu kemudian. Untungnya saya menemukan yang ini pada putaran kedua.
Timpang
1
Saya telah menggunakan solusi ini. Tanggal yang diformat ini digabungkan dengan data lain, jadi saya punya varchar ... Mudah! Tidak perlu repot memformat log tersebut di aplikasi. Namun, beberapa masalah zona waktu yang liar muncul! Tanggal saya menggunakan zona waktu UTC dan bukan zona waktu pelanggan :(
gustavohenke
2
@Whitecat Tidak tahu apakah Anda sudah memecahkan masalah Anda, tapi perhatikan casingnya! Mungkin pengaturan pemeriksaan database Anda disetel ke sesuatu seperti 'SQL_Latin1_General_CP1_CS_AS', CS adalah kata kunci di sini. Itu singkatan dari "CaseSensitiv" oleh karena itu kode Anda harus cocok dengan casing! Hal lain bisa jadi bahwa Sistem Anda adalah MySql, daripada namanya adalah date_add (). Salam;)
Nightking
3
Solusi ini akan dipengaruhi oleh masalah tahun 2038 karena fungsi dateadd membutuhkan tipe int. Dokumentasi mengatakan "Argumen nomor tidak boleh melebihi kisaran int." docs.microsoft.com/en-us/sql/t-sql/functions/… en.wikipedia.org/wiki/Year_2038_problem
Patrick H
30

Jika ada yang mendapatkan kesalahan di bawah ini:

Kesalahan overflow aritmatika mengubah ekspresi menjadi tipe data int

karena stempel waktu unix ada di bigint (bukan int), Anda dapat menggunakan ini:

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

Ganti stempel waktu hardcode untuk kolom Anda yang sebenarnya dengan unix-timestamp

Sumber: MSSQL bigint Unix Timestamp ke Datetime dengan milidetik

jmojico.dll
sumber
Mengingat waktu milidetik, bahkan lebih baik: SELECT DATEADD (ms, 1517270454852% 1000, DATEADD (S, 1517270454852/1000, '1970-01-01'))
G DeMasters
25

Seperti ini

tambahkan tanggal waktu Unix (epoch) ke tanggal dasar dalam hitungan detik

ini akan mendapatkannya untuk saat ini (2010-05-25 07: 56: 23.000)

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

Jika Anda ingin mundur, lihat http://wiki.lessthandot.com/index.php/Epoch_Date ini

SQLMenace
sumber
1
mengapa 05:00:00 dan bukan 00:00:00?
Svisstack
2
@Svisack 5 jam adalah untuk perbedaan zona waktu. 5:00:00 berarti dia GMT-5 jam
Jordy van Eijk
Bekerja seperti pesona. Jika Anda perlu menyesuaikan zona waktu, tentu lakukan itu tetapi pertimbangkan ini sangat efisien
clifton_h
7

Ini akan melakukannya:

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

Bukannya! Presisi! gunakan: ss, ms atau mcs sesuai dengan ketepatan stempel waktu. Bigint mampu menahan presisi mikrodetik.

Ovidiu Pacurar
sumber
4

Menambahkan n detik ke 1970-01-01akan memberi Anda tanggal UTC karena n , stempel waktu Unix, adalah jumlah detik yang telah berlalu sejak 00:00:00 Waktu Universal Terkoordinasi (UTC), Kamis, 1 Januari 1970 .

Di SQL Server 2016, Anda dapat mengonversi satu zona waktu ke zona waktu lainnya menggunakan AT TIME ZONE. Anda hanya perlu mengetahui nama zona waktu dalam format standar 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 |

Atau sederhananya:

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 |

Catatan:

  • Anda dapat memotong informasi zona waktu dengan mentransmisikan DATETIMEOFFSETke DATETIME.
  • Konversi tersebut memperhitungkan waktu musim panas. Waktu Pasifik adalah UTC-08: 00 pada Januari 2018 dan UTC-07: 00 pada Jun 2018.
Salman A
sumber
3

Jika waktu dalam milidetik dan seseorang perlu menyimpannya:

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

Ini membangun dari pekerjaan yang Daniel Little lakukan untuk pertanyaan ini, tetapi dengan mempertimbangkan penghematan waktu siang hari (bekerja untuk tanggal 01-01 1902 dan lebih besar karena batas int pada fungsi dateadd):

Pertama-tama kita perlu membuat tabel yang akan menyimpan rentang tanggal untuk penghematan waktu siang hari (sumber: Sejarah waktu di Amerika Serikat ):

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

Sekarang kami membuat fungsi untuk setiap zona waktu Amerika. Ini mengasumsikan waktu unix dalam milidetik. Jika dalam hitungan detik, hapus / 1000 dari kode:

Pasifik

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

Timur

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

Pusat

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

Gunung

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.dll
sumber
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
pengguna3450075
sumber
1

Saya harus menghadapi masalah ini juga. Sayangnya, tidak ada jawaban (di sini dan di lusinan halaman lain) yang memuaskan bagi saya, karena saya masih belum bisa mencapai tanggal di luar tahun 2038 karena bilangan bulat 32 bit dipasang di suatu tempat.

Solusi yang berhasil bagi saya pada akhirnya adalah menggunakan floatvariabel, jadi saya dapat memiliki setidaknya tanggal maksimal 2262-04-11T23:47:16.854775849. Namun, ini tidak mencakup seluruh datetimedomain, tetapi cukup untuk kebutuhan saya dan dapat membantu orang lain menghadapi masalah yang sama.

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

Ada beberapa hal yang perlu diperhatikan:

  • Presisi 100ns adalah persyaratan dalam kasus saya, namun ini tampaknya menjadi resolusi standar untuk cap waktu unix 64 bit. Jika Anda menggunakan resolusi lain, Anda harus menyesuaikan @ticksofdaydan baris pertama algoritma yang sesuai.
  • Saya menggunakan sistem lain yang memiliki masalah dengan zona waktu dll. Dan saya menemukan solusi terbaik untuk saya adalah selalu menggunakan UTC. Untuk kebutuhan Anda, ini mungkin berbeda.
  • 1900-01-01adalah tanggal asal untuk datetime2, sama seperti waktu 1970-01-01untuk stempel waktu unix.
  • floats membantu saya untuk memecahkan masalah tahun 2038 dan bilangan bulat yang meluap dan semacamnya, tetapi perlu diingat bahwa angka floating point tidak terlalu berkinerja dan dapat memperlambat pemrosesan sejumlah besar stempel waktu. Selain itu, float dapat menyebabkan hilangnya presisi karena kesalahan pembulatan, seperti yang Anda lihat dalam perbandingan hasil contoh untuk tanggal maksimum di atas (di sini, kesalahannya sekitar 1,4425ms).
  • Di baris terakhir algoritme ada cor ke datetime. Sayangnya, tidak ada cast eksplisit dari nilai numerik ke datetime2diizinkan, tetapi diizinkan untuk mentransmisikan numerik datetimesecara eksplisit dan ini, pada gilirannya, diterapkan secara implisit ke datetime2. Ini mungkin benar, untuk saat ini, tetapi dapat berubah di versi SQL Server yang akan datang: Mungkin akan ada dateadd_big()fungsi atau pemeran eksplisit untuk datetime2akan diizinkan atau pemeran eksplisit datetimeakan tidak diizinkan, jadi ini mungkin rusak atau mungkin ada cara yang lebih mudah suatu hari nanti.
Chris Tophski
sumber
1

Untuk GMT, berikut adalah cara termudah:

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

Lebih baik? Fungsi ini mengubah unixtime dalam milidetik menjadi datetime. Ini hilang milidetik, tetapi masih sangat berguna untuk pemfilteran.

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

Solusinya bisa sebagai berikut:

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

@DanielLittle memiliki jawaban termudah dan paling elegan untuk pertanyaan spesifik. Namun, jika Anda tertarik untuk mengonversi ke zona waktu tertentu DAN mempertimbangkan DST (Waktu Musim Panas), berikut ini berfungsi dengan baik:

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

Catatan: Solusi ini hanya berfungsi di SQL Server 2016 dan yang lebih baru (dan Azure).

Untuk membuat fungsi:

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

Anda dapat memanggil fungsi seperti ini:

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