SQL Server'da bigint'i (UNIX zaman damgası) datetime biçimine nasıl dönüştürebilirim?


Yanıtlar:


58

Deneyin:

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 UTC-> yerel dönüştürme için. 10 Haziran'ı Şubat ayında çevirmeye çalışırsanız yaz / kış saatinin yine kapalı olacağını unutmayın.
Andomar

11
UTC-> yerel dönüştürme için -1. Yaz saati uygulamasını doğru şekilde işlemiyor. Benim için bu yanlıştır.
Pavel Horal

Yaratıcı çözüm için +1! Harika çalışıyor. Bilginize, SQL'de bir sözdizimi hatası var. İlk "DECLARE" satırının sonundaki noktalı virgülün ardından virgül çıktığı için kaldırılması gerekir.
Seth

2
Benim için çalışmıyor. 1517270400000 ile deniyorum ve şu hatayı alıyorum: İfadeyi int veri türüne dönüştürürken aritmetik taşma hatası.
Danimarkalı

1
Ayrıca bir taşma oluyordu, normalde milisaniyelerin dahil olduğu anlamına gelir, basitçe şu şekilde çözülür: src_table'dan dbo.fn_ConvertToDateTime (src_column / 1000) öğesini seçin;
erişim

309

Bu benim için çalıştı:

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

1970-01-01'in nedenini merak eden biri durumunda, buna Epoch zamanı denir .

Aşağıda Wikipedia'dan bir alıntı var:

00:00:00 Eşgüdümlü Evrensel Saat (UTC), 1 Ocak 1970 Perşembe, [1] [not 1] artık saniye sayılmadan geçen saniye sayısı.


18
Bu doğru olarak işaretlenmelidir. Keşke buraya her geldiğimde bu yanıtı tekrar
yükseltebilseydim

2
@BenDundee Sana gerçekten katılıyorum. Ne kadar zarif bir çözüm. Her yerde bir formül aradım ve sonunda bir hafta sonra hatalarla karşılaşmaya başladığımda tekrar aramaya gitmek zorunda kaldım. Neyse ki bunu ikinci turda buldum.
Lopsided

1
Bu çözümü kullanıyorum. Bu biçimlendirilmiş tarih diğer verilerle birleştirildi, bu yüzden bir varchar'ım vardı ... Kolay! Uygulamada bu günlükleri biçimlendirmeye gerek yok. Ancak, bazı vahşi saat dilimi sorunları ortaya çıktı! Tarihlerim müşterinin saat dilimi yerine UTC saat dilimini kullanıyordu :(
gustavohenke

2
@Whitecat Sorununuzu çözdünüz mü bilmiyorum ama kasaya dikkat edin! Belki veritabanı harmanlama ayarınız 'SQL_Latin1_General_CP1_CS_AS' gibi bir şeye ayarlanmış olabilir, CS buradaki anahtar kelimedir. "CaseSensitiv" anlamına gelir, çünkü kodunuz büyük / küçük harflerle eşleşmelidir! Diğer bir nokta, Sisteminizin MySql olması, adın date_add () olması olabilir. Saygılarımızla;)
Nightking

3
Dateadd işlevi bir int türü gerektirdiğinden, bu çözüm 2038 yılı sorunundan etkilenecektir. Dokümantasyon "Sayı bağımsız değişkeni int aralığını aşamaz" diyor. docs.microsoft.com/en-us/sql/t-sql/functions/… en.wikipedia.org/wiki/Year_2038_problem
Patrick H

34

Aşağıdaki hatayı alan biri varsa:

İfadeyi int veri türüne dönüştürürken aritmetik taşma hatası

unix zaman damgası bigint (int yerine) olduğu için, bunu kullanabilirsiniz:

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

Gerçek sütununuz için sabit kodlanmış zaman damgasını unix-zaman damgası ile değiştirin

Kaynak: MSSQL bigint Unix Zaman Damgası, milisaniye ile Datetime


Devir milisaniyeleri verildiğinde, daha da iyisi: DATEADD SEÇİN (ms, 1517270454852% 1000, DATEADD (S, 1517270454852/1000, '1970-01-01'))
G DeMasters

teşekkür ederim . bu 1462924862735870900 TIMES olarak oylanmalıdır !!!!!!!!!!!!!!!!!!!!!
John

Yardımcı olmaktan mutluluk duyarım @John
jmojico

26

Bunun gibi

Unix (epoch) tarih saatini temel tarihe saniye cinsinden ekleyin

şimdilik onu alacak (2010-05-25 07: 56: 23.000)

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

Ters gitmek istiyorsanız, şu http://wiki.lessthandot.com/index.php/Epoch_Date adresine bir göz atın.


1
neden 00:00:00 yerine 05:00:00?
Svisstack

2
@Svisstack 5 saat saat dilimi farkı içindir. 5:00:00 GMT-5 saat olduğu anlamına gelir
Jordy van Eijk

Tıkır tıkır çalışıyor. Saat dilimini ayarlamanız gerekiyorsa, o zaman kesinlikle yapın, ancak bunu çok verimli bir şekilde düşünün
clifton_h

7

Bunu yapacak:

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

Yerine! Hassas! kullanım: zaman damgasının kesinliğine göre ss, ms veya mcs. Bigint, mikrosaniye hassasiyetini tutabilir.



4

N saniye eklemek 1970-01-01size bir UTC tarihi verecektir çünkü n , Unix zaman damgası , 1 Ocak 1970 Perşembe 00:00:00 Eşgüdümlü Evrensel Saatten (UTC) bu yana geçen saniye sayısıdır .

SQL Server 2016'da, kullanarak bir saat dilimini diğerine dönüştürebilirsiniz AT TIME ZONE. Sadece saat diliminin adını Windows standart biçiminde bilmeniz gerekir:

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 |

Ya da sadece:

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 |

Notlar:

  • Sen döküm tarafından saat dilimi bilgilerini kesmek olabilir DATETIMEOFFSETiçin DATETIME.
  • Dönüştürme, gün ışığından yararlanma süresini hesaba katar. Pasifik saati Ocak 2018'de UTC-08: 00 ve Haziran 2018'de UTC-07: 00 idi.

3

Zaman milisaniye cinsinden ise ve birinin korunması gerekiyorsa:

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

Bu, Daniel Little'ın bu soru için yaptığı işin temelini oluşturuyor, ancak gün ışığından yararlanma süresini hesaba katıyor (dateadd işlevindeki int limit nedeniyle 01-01 1902 ve daha büyük tarihler için geçerlidir):

Öncelikle gün ışığından yararlanma saati için tarih aralıklarını saklayacak bir tablo oluşturmamız gerekiyor (kaynak: Amerika Birleşik Devletleri'nde zamanın geçmişi ):

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

Şimdi her Amerikan saat dilimi için bir fonksiyon oluşturuyoruz. Bu, unix zamanının milisaniye cinsinden olduğunu varsayar. Saniyeler içindeyse, / 1000'i koddan kaldırın:

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

Doğu

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

Merkez

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

Dağ

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

Ben de bu problemle yüzleşmek zorunda kaldım. Ne yazık ki, yanıtların hiçbiri (burada ve diğer düzinelerce sayfada) bana tatmin edici gelmedi, çünkü bir yerlerde 32 bitlik tamsayılar nedeniyle 2038 yılından sonraki tarihlere hala ulaşamıyorum.

Sonunda benim için işe floatyarayan bir çözüm, değişkenleri kullanmaktı , böylece en azından bir maksimum tarihim olabilirdi 2262-04-11T23:47:16.854775849. Yine de, bu tüm datetimealanı kapsamıyor , ancak ihtiyaçlarım için yeterli ve aynı sorunla karşılaşan başkalarına yardımcı olabilir.

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

Dikkate alınması gereken bazı noktalar var:

  • Benim durumumda 100ns hassasiyet şarttır, ancak bu 64 bit unix zaman damgaları için standart çözünürlük gibi görünüyor. Başka bir çözünürlük kullanırsanız @ticksofday, algoritmanın ilk satırını buna göre ayarlamanız gerekir .
  • Saat dilimleriyle vb. Sorunları olan diğer sistemleri kullanıyorum ve benim için en iyi çözümün her zaman UTC kullanmak olduğunu buldum. İhtiyaçlarınız için bu farklılık gösterebilir.
  • 1900-01-01datetime2tıpkı 1970-01-01unix zaman damgaları için olduğu gibi, başlangıç ​​tarihidir .
  • floats, 2038 yılı problemini ve tam sayı taşmalarını çözmeme yardımcı oldu, ancak kayan noktalı sayıların çok performanslı olmadığını ve büyük miktarda zaman damgasının işlenmesini yavaşlatabileceğini unutmayın. Ayrıca, yukarıdaki maksimum tarih için örnek sonuçların karşılaştırmasında görebileceğiniz gibi, kayan değerler yuvarlama hataları nedeniyle hassasiyet kaybına neden olabilir (burada hata yaklaşık 1.4425ms'dir).
  • Algoritmanın son satırında bir atama var datetime. Maalesef, sayısal değerlerden datetime2izin verilene datetimeaçık bir dönüşüm yoktur , ancak sayısal değerlerin açıkça atılmasına izin verilir ve bu da dolaylı olarak örtük olarak atılır datetime2. Bu şimdilik doğru olabilir, ancak SQL Server'ın gelecekteki sürümlerinde değişebilir: Ya bir dateadd_big()işlev olacak ya da açık atamaya datetime2izin verilecek ya da açık atama datetimeyapılmayacaktır, bu yüzden bu ya kırılabilir ya da gelebilir bir gün daha kolay bir yol.

1

GMT için en kolay yol şudur:

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

0

Daha iyi? Bu fonksiyon unixtime'ı milisaniye cinsinden datetime'a çevirir. Milisaniyeler kaybetti, ancak yine de filtreleme için çok kullanışlı.

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

Çözüm aşağıdaki gibi olabilir:

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, belirli bir soruya en kolay ve en zarif cevaba sahiptir. Ancak, belirli bir saat dilimine dönüştürmekle VE DST'yi (Yaz Saati Uygulaması) hesaba katmakla ilgileniyorsanız, aşağıdakiler işe yarar:

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

Not: Bu çözüm yalnızca SQL Server 2016 ve üzeri (ve Azure) üzerinde çalışır.

Bir işlev oluşturmak için:

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

İşlevi şu şekilde çağırabilirsiniz:

SELECT   dbo.ConvertUnixTime([UnixTimestamp])
FROM     YourTable
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.