如何比较不同精度的日期

How to compare dates with different precision

我问 如何比较 datetime2 值,但忽略了纳秒。由于涉及一些舍入,因此无法正确比较这些值。

在 java 中,我可以从 DateTimestamp 中得到一个 Long 值,它表示自 1970 年 1 月 1 日以来的毫秒数,00:00:00格林威治标准时间。这是比较 java 中日期的一种非常安全的方法。

有没有办法

A) 从 datetime2 值中获取一个数值,该值表示毫秒数

B) 将舍入从毫秒更改为向下而不是向上舍入。

示例值:

2018-01-24 16:20:51.0715460
2018-01-25 09:52:04.1946950
2018-01-25 09:52:04.1946950

应与

匹配
2018-01-24 16:20:51.0710000
2018-01-25 09:52:04.1940000
2018-01-25 09:52:04.1940000

目前我正在使用 cast(date as datetime2(3)) 来获得最精确的结果,但由于四舍五入,它们仍然不匹配。

任何人都可以给我一个方便的方法来比较上面的值以匹配吗?

您可以通过从未舍入的日期中提取毫秒数来执行此操作,使用取模函数从 1000000 中获取余数,然后从原始日期中减去它,例如

SELECT  A,
        B,
        RoundDown = DATEADD(NANOSECOND, -DATEPART(NANOSECOND, A) % 1000000, A),
        Match = CASE WHEN DATEADD(NANOSECOND, -DATEPART(NANOSECOND, A) % 1000000, A) = B THEN 1 ELSE 0 END
FROM    (VALUES
            (CONVERT(DATETIME2(7), '2018-01-24 16:20:51.0715460'), CONVERT(DATETIME2(7), '2018-01-24 16:20:51.0710000')),
            (CONVERT(DATETIME2(7), '2018-01-25 09:52:04.1946950'), CONVERT(DATETIME2(7), '2018-01-25 09:52:04.1940000')),
            (CONVERT(DATETIME2(7), '2018-01-25 09:52:04.1946950'), CONVERT(DATETIME2(7), '2018-01-25 09:52:04.1940000'))
        ) x (A, B);

给出:

A                               B                               RoundDown                       Match
-------------------------------------------------------------------------------------------------------
2018-01-24 16:20:51.0715460     2018-01-24 16:20:51.0710000     2018-01-24 16:20:51.0710000     1
2018-01-25 09:52:04.1946950     2018-01-25 09:52:04.1940000     2018-01-25 09:52:04.1940000     1
2018-01-25 09:52:04.1946950     2018-01-25 09:52:04.1940000     2018-01-25 09:52:04.1940000     1

为了完整性,这里和正常的四舍五入、四舍五入、四舍五入是一样的

SELECT  Original = A,
        RoundDown = DATEADD(NANOSECOND, -DATEPART(NANOSECOND, A) % 1000000, A),
        RoundUp = DATEADD(NANOSECOND, 1000000 - DATEPART(NANOSECOND, A) % 1000000, A),
        RoundNormal = CONVERT(DATETIME2(3), A)
FROM    (VALUES
            (CONVERT(DATETIME2(7), '2018-01-24 16:20:51.0715460')),
            (CONVERT(DATETIME2(7), '2018-01-25 09:52:04.1946950')),
            (CONVERT(DATETIME2(7), '2018-01-25 09:52:04.1946950')),
            (CONVERT(DATETIME2(7), '2018-01-25 09:52:04.1943950'))
        ) x (A);

一个快速的选择是转换为 varchar(23),这实际上会截断值

例子

Declare @YourTable Table ([D1] datetime2)
Insert Into @YourTable Values 
 ('2018-01-24 16:20:51.0715460')
,('2018-01-25 09:52:04.1946950')
,('2018-01-25 09:52:04.1946950')

Select * 
      ,NewVal = convert(varchar(23),D1)+'0000'
from @YourTable

Returns

D1                             NewVal
2018-01-24 16:20:51.0715460    2018-01-24 16:20:51.0710000
2018-01-25 09:52:04.1946950    2018-01-25 09:52:04.1940000
2018-01-25 09:52:04.1946950    2018-01-25 09:52:04.1940000