【问题标题】:SQL Server datetime to bigint (epoch) overflowSQL Server 日期时间到 bigint(纪元)溢出
【发布时间】:2013-03-26 10:32:37
【问题描述】:

我有一个值为 2013-03-22 15:19:02.000 的“日期时间”列

我需要将此值转换为纪元时间并将其存储在“bigint”字段中

上述时间的实际epoch值是,1363945741898,当我使用时

  select DATEDIFF(s, '1970-01-01 00:00:00', '2013-03-22 15:19:02.000')

我知道,1363965542,当我使用时

select DATEDIFF(ms, '1970-01-01 00:00:00', '2013-03-22 15:19:02.000')

我明白了,

消息 535,第 16 级,状态 0,第 1 行 datediff 函数导致溢出。分隔两个日期/时间实例的日期部分的数量太大。尝试将 datediff 与不太精确的日期部分一起使用。

如何从'datetime'字段中获取精确的纪元值

我使用 SQL Server 2008。这也应该适用于 2005。

【问题讨论】:

  • 您的日期时间在哪个时区?距离格林威治标准时间有几个半小时的路程。也许在印度? (我想知道 SQL Server 是否可能使用 GMT 作为 1970-01-01 的时区,因为它没有可以追溯到那么远的时区信息,以及 2013 年的本地时区。)
  • 你说要以epoch value = unix time,也就是以秒为单位,那为什么第二次查询时要以毫秒为单位查询呢?
  • @MattGibson India IST
  • 人力资源部。出于好奇,select DATEDIFF(s, '1970-01-01 00:00:00Z', '2013-03-22 15:19:02Z') 给了你什么? (使用 Z 应该产生一个基于 GMT 而不是日期时间的日期时间偏移量。)
  • @aweis 我应该以毫秒为单位存储它

标签: sql-server datetime


【解决方案1】:

这是一个示例,未经测试,由徒手编写:)

declare @v_Date datetime
set @v_Date = '2013-03-22 15:19:02.000'

declare @v_DiffInSeconds integer
declare @v_DiffInMSeconds bigint

select @v_DiffInSeconds = DATEDIFF(s, '1970-01-01 00:00:00', @v_Date)
select @v_DiffInMSeconds = cast(@v_DiffInSeconds as bigint) * 1000 + cast(DATEPART(ms, @v_Date) as bigint)

编辑 我在下面做了这个例子来说明时区转换。给定的时间戳(以秒为单位,我删除了最后三位数字“898”)在这里通过添加 5.5 小时(19800 秒)转换为本地 IST 时区,然后我将其从本地时间转换回时间戳再次格林威治标准时间。下面的计算与问题中的值相匹配(以秒为单位)。

declare @v_time datetime
set @v_time = '1970-01-01 00:00:00'

declare @v_date datetime
set @v_date = '2013-03-22 15:19:01'

-- This returns "March, 22 2013 15:19:01"
select dateadd(s, (1363945741 + 19800), @v_time)

-- This returns "1363945741"
select datediff(s, @v_time, @v_date) - 19800

【讨论】:

  • 这也返回 1363965542000
  • 我尝试将 epochconverter.com 上的整数值转换为 1363945741898 评估为 2013 年 3 月 22 日星期五 09:49:01 GMT 所以我不确定你是如何计算你的价值的,因为你得到它到 2013 年-03-22 15:19:02.000
  • 在我的时区,2013 年 3 月 22 日星期五下午 3:19:01 GMT+5.5
  • 我在答案中添加了一个示例,我在 GMT 和 IST 之间来回转换。
  • 在您的第一个代码块中,我在计算 ms 之前从秒数中减去了 19800。它给了我正确的结果。谢谢。
【解决方案2】:

当试图获得精确的毫秒数时,我们会得到溢出异常。我们可以得到直到秒的值并乘以 1000。

这相当于javascript中的new Date().getTime()

使用以下语句以秒为单位获取时间。

SELECT cast(DATEDIFF(s, '1970-01-01 00:00:00.000', '2016-12-09 16:22:17.897' ) as bigint)

使用下面的语句来获取以毫秒为单位的时间。

SELECT cast(DATEDIFF(s, '1970-01-01 00:00:00.000', '2016-12-09 16:22:17.897' ) as bigint) * 1000

使用以下语句将纪元转换为人类可读的日期时间:

select DATEADD(s, 1481300537, '1970-01-01 00:00:00')

【讨论】:

  • 最后一条语句的结果是:Arithmetic overflow error converting expression to data type int. 如果您有更大的日期。
【解决方案3】:

从纪元到日期时间

create function [dbo].[EpochToDate](@Date bigint)
returns datetime
begin
    return (select dateadd(s, @Date, '19700101'))
end 

【讨论】:

    【解决方案4】:

    使用以下代码从纪元时间获取人类可读的日期

    select DATEADD(s,convert(bigint,@date)/2, DATEADD(s, convert(bigint,@date)/2, '1970-01-01 00:00:00'))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-17
      • 1970-01-01
      • 2019-10-03
      • 2021-05-26
      • 2019-07-14
      • 2015-07-13
      • 2013-05-19
      • 2016-03-07
      相关资源
      最近更新 更多