【问题标题】:Getting today's midnight time as UTC获取今天的午夜时间为 UTC
【发布时间】:2011-11-04 13:33:02
【问题描述】:

我有以下查询,它将今天的午夜值 (UTC) 计算为日期时间:

SELECT CONVERT(DATE,GETDATE())+(GETDATE()-GETUTCDATE())

结果:2011-11-03 19:00:00.000(适用于 2011 年 11 月 4 日的 GMT-5)

不仅如此,有时它还会返回如下值:

2011-11-03 19:00:00.003
2011-11-03 19:00:00.007
2011-11-03 19:00:00.010

...,错了!

必须有更好的方法来做到这一点。

【问题讨论】:

    标签: sql-server sql-server-2008 sql-server-2008-r2


    【解决方案1】:

    我已经通过使用 DATEADD 和 DATEDIFF 以及 GETDATE() 和 GETUTCDATE() 的解决方案回答了这个问题,类似于原始问题中给出的示例,但从那时起我发现了 datetimeoffset 数据类型 added in SQL Server 2008。这会存储一个日期时间和一个时区偏移量。

    如何使用此类型取决于您是否要更改现有数据的数据类型。如果您不想更改任何内容,以下语句将返回本地时间为午夜的 datetime 类型:

    SELECT CONVERT(datetime, SWITCHOFFSET(CONVERT(datetimeoffset, 
        CONVERT(date, GETDATE())), 
        DATENAME(TzOffset, SYSDATETIMEOFFSET())))
    

    您还可以使用以下方法将任何 UTC 时间转换为本地时间:

    SELECT CONVERT(datetime, SWITCHOFFSET(CONVERT(datetimeoffset, 
            @myutctime, 
            DATENAME(TzOffset, SYSDATETIMEOFFSET())))
    

    datetimeoffset 类型仅适用于 SQL2008 及更高版本。如果您需要在 2005 及以下版本中执行此操作,您可以使用与原始问题中的解决方案类似的解决方案,但要考虑到 GETDATE() - GETUTCDATE() 不是原子操作并且可能涉及时间之间的毫秒差异这一事实两人被处决。

    SELECT DATEADD(minute, 
        DATEDIFF(minute, GETUTCDATE(), GETDATE()), 
        CONVERT(datetime, CONVERT(date, GETDATE())))
    

    这将占用GETDATE() 和GETUTCDATE() 之间的分钟数,并将它们添加到当地的午夜时间。不幸的是,您必须将日期转换回日期时间,因为如果您给它一个日期,DATEADD 将无法使用分钟。我建议将其包装到用户定义的函数中以使其看起来不那么冗长,例如

    CREATE FUNCTION dbo.MidnightASUTC(@dt as datetime)
    RETURNS datetime
    AS
    BEGIN
        RETURN DATEADD(minute, 
            DATEDIFF(minute, GETUTCDATE(), GETDATE()),
            CONVERT(datetime, CONVERT(date, @dt)))
    END
    
    SELECT dbo.MidnightAsUTC(GETDATE())
    

    【讨论】:

    • 您需要在对 DATEDIFF:DATEDIFF(hour, GETUTCDATE(), GETDATE()) 的调用中反转 GETDATE() 和 GETUTCDATE() 以获得正确的结果,但我尝试运行大约 100 次并且至少获得了正确的时间。
    • 糟糕,我已经把它反转了。我还更改了使用 DATEADD(minute...) 的答案,因为小时方法不会处理与 UTC 相差 1/2 小时的国家/地区。
    • 我想知道您提供的 UDF 是否存在性能损失,将其设为返回 1 行/1 列结果和值的内联 TVF 是否有意义?
    • 我现在已经完全修改了这个答案,因为我刚刚遇到了 datetimeoffset 数据类型,它存储了一个时区偏移量。原始答案留给任何需要在 SQL2008 之前执行此操作的人。
    【解决方案2】:

    对于您所描述的特定场景(“今天的午夜值 (UTC) 作为日期时间”),编程方法是有意义的,但如果您需要将其扩展到不同的问题(什么是午夜今年夏天的UTC?),您可能想要使用日历表(以考虑夏令时等)。

    【讨论】:

      猜你喜欢
      • 2012-10-19
      • 1970-01-01
      • 2020-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-23
      • 1970-01-01
      相关资源
      最近更新 更多