【问题标题】:Convert specific BigInt to DateTime in T-SQL在 T-SQL 中将特定 BigInt 转换为 DateTime
【发布时间】:2016-11-29 18:03:39
【问题描述】:

我有 bigInt:635307578922100000,我需要将其转换为 DateTime

我尝试了几种方法来做到这一点:

SELECT 
    DATEADD(S, CONVERT(bigint,635307578922100000) / 1000, CONVERT(DATETIME, '1-1-1970 00:00:00')) 

和:

SELECT 
    DATEADD(ms, 635307578922100000 / 86400000, (635307578922100000 / 86400000) +25567)

虽然我发现上面的代码适用于 bigInts,例如:1283174502729,但我的 bigInt 出现以下错误:

Msg 8115 ... 将表达式转换为数据时出现算术溢出错误 输入日期时间。

有人知道怎么解决吗?

【问题讨论】:

  • 对于给定的输入“635307578922100000”,您的预期结果是什么
  • 看起来这些是蜱虫。 Convert .NET Ticks to SQL Server DateTime 的可能重复项 - 使用此处的答案给出 2016-07-26 09:12:00.000
  • 您需要将此值转换为自 01.01.1900 00:00:00 以来的小时数,它是适合 int 的最大日期部分精度。然后向左添加 ms。
  • 那一天是几号?就算是微秒,也还是2万年+
  • @Bridge 我自己也想不到。非常感谢!

标签: sql sql-server datetime bigint dateadd


【解决方案1】:

这里有一些计算可以将 bigint 计算为日期时间。

SELECT
tick.value

-- Subtrack the amount of ticks for 1900-01-01 and divide that number by the ticks in 1 day.
-- Then cast or convert that smaller number to a datetime
-- But only accurate to the second.
-- 864000000000 = (10000000 * 24 * 60 * 60)
 , CAST((tick.value - 599266080000000000) / 864000000000 AS datetime) as DateTimeCalc1

-- Subtrack the amount of ticks for 1900-01-01 and divide by the ticks in 1 minute.
-- Then add that smaller number as minutes to 1900-01-01
-- Only accurate to the minute
 , DATEADD(MINUTE, ((tick.value - 599266080000000000) / 600000000), CAST('1900-01-01' AS DATETIME)) as DateTimeCalc2

-- Same method as for DateTimeCalc2, but include the milliseconds.
-- Accurate to the millisecond
 , DATEADD(MILLISECOND, FLOOR((((tick.value - 599266080000000000)/10000)%60000)), DATEADD(MINUTE, FLOOR((tick.value - 599266080000000000)/600000000), CAST('1900-01-01' AS DATETIME))) as DateTimeCalc3

FROM (values 
  (convert(bigint,635307578922100000))
 ,(convert(bigint,599266080000000000))
 ,(convert(bigint,630823257457000000))
 ,(convert(bigint,646602048000000000))
) AS tick(value);

结果:

value               DateTimeCalc1           DateTimeCalc2           DateTimeCalc3
------------------ ----------------------- ----------------------- -----------------------
635307578922100000 2014-03-18 16:44:52.207 2014-03-18 16:44:00.000 2014-03-18 16:44:52.210
599266080000000000 1900-01-01 00:00:00.000 1900-01-01 00:00:00.000 1900-01-01 00:00:00.000
630823257457000000 2000-01-01 12:15:45.697 2000-01-01 12:15:00.000 2000-01-01 12:15:45.700
646602048000000000 2050-01-01 00:00:00.000 2050-01-01 00:00:00.000 2050-01-01 00:00:00.000

只要稍加改动,这些日期时间就会被截断或舍入到秒。

SELECT tick.value

-- Truncated
, CAST(CONVERT(varchar, CAST((tick.value - 599266080000000000) / 864000000000 AS datetime),20) AS datetime) as DateTimeTruncated

-- Rounded
, CAST(CAST(CAST((tick.value - 599266080000000000) / 864000000000 AS datetime) as datetime2(0)) AS datetime) as DateTimeRounded

-- For dates between 1981-12-14 and 2118-01-19, one could add seconds to 2050-01-01. 
, DATEADD(SECOND, ((tick.value - 646602048000000000) / 10000000), cast('2050-01-01' as datetime)) as DateTimeSecondsAdded

FROM (values 
(630823257457000000),
(635307578922100000),
(662380857456770000)
) tick(value);

【讨论】:

  • 完美解决方案。谢谢。
【解决方案2】:

我认为它是在滴答声中(产量 2014-03-18 16:44:52.210)。这是解决方案:

SELECT DATEADD(
    MILLISECOND,
    FLOOR(((635307578922100000-599266080000000000)%(10000000*60))/10000),
    DATEADD(
        MINUTE,
        FLOOR((635307578922100000-599266080000000000)/(10000000*60)),
        '01-01-1900'))

这个神奇的值 599266080000000000 是在 PowerShell 中计算的 0001-01-01 和 1900-01-01 之间的刻度数,如下所示:

([DateTime]::Parse('1900-01-01')-[DateTime]::MinValue).Ticks

需要进行转换,因为 DATEADD 不适用于 bigint(需要 int)。 SQL Server 日期时间也限制为 1753 年 1 月 1 日。

【讨论】:

    猜你喜欢
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    • 1970-01-01
    • 2011-11-15
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多