将 Epoch 转换为 DateTime SQL 服务器(超过 2038 年)
Convert Epoch to DateTime SQL Server (Exceeds Year 2038)
如果纪元超过 2038 年,如何将纪元转换为日期时间 SQL 服务器?
中的答案无效。
示例:
SELECT DATEADD(ss, 2713795200000 / 1000, '19700101')
2055 年 12 月 30 日星期四16:00:00格林威治标准时间
创建一个将纪元转换为日期时间的函数,并在您的查询中使用它们,例如
以下
create FUNCTION [dbo].[from_unixtime] (@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;
然后在您的查询中使用此函数
DATEADD 函数假定 INT 作为您日期的增量,要绕过 INT 的限制,您可以降低纪元的精度,或者执行稍微复杂的代码以保留纪元的精度。
这会将精度降低到分钟:
SELECT DATEADD(MINUTE,@YourEpoch/60/1000, '1/1/1970')
这个将你的纪元拆分为几天和几毫秒,然后将它们合并到一个日期时间
CREATE FUNCTION [dbo].[fn_EpochToDatetime] (@Epoch BIGINT)
RETURNS DATETIME
AS
BEGIN
DECLARE @Days AS INT, @MilliSeconds AS INT
SET @Days = @Epoch / (1000*60*60*24)
SET @MilliSeconds = @Epoch % (1000*60*60*24)
RETURN (SELECT DATEADD(MILLISECOND, @MilliSeconds, DATEADD(DAY, @Days, '1/1/1970')))
END;
但是,我不太确定为什么第二个解决方案不如我预期的那么精确。
基于上述响应,提供的解决方案有效,但无法防止尝试转换为 SQL 服务器超出范围的日期。
创建函数dbo.unixTimestampConversion (
@unixTime bigInt
)
returns 日期时间 2(7)
作为
开始
declare
@output dateTime2(7)
, @days int
, @ms int
, @x int = (1000 * 60 * 60 * 24)
;
set @days = @unixTime / @x
;
set @ms = @unixTime % @x
;
if (@unixTime < 32503593600000 and @unixTime > -2208988800000)
begin
set @output = dateAdd (millisecond, @ms, dateAdd (day, @days, '1/1/1970'))
;
end
;
else if (@unixTime <= -2208988800000)
begin
set @output = '1/1/1900'
;
end
;
else if (@unixTime >= 32503593600000)
begin
set @output = '12/31/2999'
;
end
;
return @output
;
end
;
您可以直接将纪元时间分配给您的日期时间(我在 SQL Server 15.0 上试过)。虽然它认为这个数字是自 1900-1-1 00:00:00 以来的天数,所以你必须加上 2208988800(70 年的秒数)然后除以 86400(一天的秒数)。
DECLARE @time DATETIME = (2208988800.0 + [your epoch time in seconds])/86400;
但是,它似乎比给定的纪元晚了 0.007 秒或 0.003 秒。另外,我不确定这是否比 DATEADD()
函数快。
如果纪元超过 2038 年,如何将纪元转换为日期时间 SQL 服务器?
示例:
SELECT DATEADD(ss, 2713795200000 / 1000, '19700101')
2055 年 12 月 30 日星期四16:00:00格林威治标准时间
创建一个将纪元转换为日期时间的函数,并在您的查询中使用它们,例如 以下
create FUNCTION [dbo].[from_unixtime] (@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;
然后在您的查询中使用此函数
DATEADD 函数假定 INT 作为您日期的增量,要绕过 INT 的限制,您可以降低纪元的精度,或者执行稍微复杂的代码以保留纪元的精度。
这会将精度降低到分钟:
SELECT DATEADD(MINUTE,@YourEpoch/60/1000, '1/1/1970')
这个将你的纪元拆分为几天和几毫秒,然后将它们合并到一个日期时间
CREATE FUNCTION [dbo].[fn_EpochToDatetime] (@Epoch BIGINT)
RETURNS DATETIME
AS
BEGIN
DECLARE @Days AS INT, @MilliSeconds AS INT
SET @Days = @Epoch / (1000*60*60*24)
SET @MilliSeconds = @Epoch % (1000*60*60*24)
RETURN (SELECT DATEADD(MILLISECOND, @MilliSeconds, DATEADD(DAY, @Days, '1/1/1970')))
END;
但是,我不太确定为什么第二个解决方案不如我预期的那么精确。
基于上述响应,提供的解决方案有效,但无法防止尝试转换为 SQL 服务器超出范围的日期。
创建函数dbo.unixTimestampConversion ( @unixTime bigInt ) returns 日期时间 2(7) 作为 开始
declare
@output dateTime2(7)
, @days int
, @ms int
, @x int = (1000 * 60 * 60 * 24)
;
set @days = @unixTime / @x
;
set @ms = @unixTime % @x
;
if (@unixTime < 32503593600000 and @unixTime > -2208988800000)
begin
set @output = dateAdd (millisecond, @ms, dateAdd (day, @days, '1/1/1970'))
;
end
;
else if (@unixTime <= -2208988800000)
begin
set @output = '1/1/1900'
;
end
;
else if (@unixTime >= 32503593600000)
begin
set @output = '12/31/2999'
;
end
;
return @output
;
end
;
您可以直接将纪元时间分配给您的日期时间(我在 SQL Server 15.0 上试过)。虽然它认为这个数字是自 1900-1-1 00:00:00 以来的天数,所以你必须加上 2208988800(70 年的秒数)然后除以 86400(一天的秒数)。
DECLARE @time DATETIME = (2208988800.0 + [your epoch time in seconds])/86400;
但是,它似乎比给定的纪元晚了 0.007 秒或 0.003 秒。另外,我不确定这是否比 DATEADD()
函数快。