将unix epoch时间戳转换为TSQL日期时间

lin*_*ski 5 t-sql epoch unix-timestamp

我发现只有一个类似的问题,但对于MySQL.

我正在开发一个Web服务,不得不查询数据库(MS SQL服务器).由于我无法得到正确的结果,我决定通过SQL客户端测试查询.Web服务使用Hibernate访问数据库,所有时间值始终表示为长值(unix纪元时间).为了测试它,我需要将unix时间戳转换为TSQL时间戳.这就是我想出的:

select dateadd(ms,123,'1970-01-01 00:00:00.0');
Run Code Online (Sandbox Code Playgroud)

哪个输出:

1970-01-01 00:00:00.123
Run Code Online (Sandbox Code Playgroud)

但是,我的实际数据有点大

select dateadd(ms,1359016610667 ,'1970-01-01 00:00:00.0');
Run Code Online (Sandbox Code Playgroud)

哪个输出:

Error code 0, SQL state 22001: Data truncation
Error code 8115, SQL state 22003: Arithmetic overflow error converting expression to data type int.
Run Code Online (Sandbox Code Playgroud)

所以,我尝试过:

select dateadd(ms,CAST (1359016610667 AS BIGINT) ,'1970-01-01 00:00:00.0');
Run Code Online (Sandbox Code Playgroud)

它输出完全相同的错误.为了安全起见,我尝试过:

select CAST (1359016610667 AS BIGINT) 
Run Code Online (Sandbox Code Playgroud)

哪个输出:

1359016610667
Run Code Online (Sandbox Code Playgroud)

我确保java long等同于TSQL bigint - 它们都很8 B长.重读dateadd()文档显示以下内容:

DATEADD(datepart,number,date)
....
number
是一个表达式,可以解析为添加到date的datepart的int.用户定义的变量有效.

如果我理解正确,这意味着这种方法不能用于将unix时间戳转换为TSQL时间戳,这很好地原谅了我的语言,但只是简单的延迟.

我的问题是:

  • 我对这种情况的解释是否正确?
  • 是否还有其他行程在TSQL中进行此转换?

PS
修改date参数('1970-01-01 00:00:00.0')是不可接受的解决方案.我正在调试,我不想重新计算毫秒数:)

Ben*_*Ben 13

容易,首先添加整天,然后添加剩余的ms.一天有86,400,000毫秒.

declare @unixTS bigint
set @unixTS = 1359016610667


select dateadd(ms, @unixTS%(3600*24*1000), 
    dateadd(day, @unixTS/(3600*24*1000), '1970-01-01 00:00:00.0')
)
Run Code Online (Sandbox Code Playgroud)

结果是 2013-01-24 08:36:50.667


小智 7

对于那些较长的时代,这应该是完美的。

SELECT DATEADD(SECOND, 1359016610667 / 1000, '19700101 00:00')
Run Code Online (Sandbox Code Playgroud)

  • 这种仅添加秒数而不是毫秒和天数的方法(如 @ben 的答案)会在处理像“2099 年 12 月 31 日”这样的日期时,当 SQL 尝试将要添加的秒数转换为 int 时导致算术溢出错误。 (2认同)