【问题标题】:Calculate time at specific Timezone, from UTC Time从 UTC 时间计算特定时区的时间
【发布时间】:2020-01-09 08:27:36
【问题描述】:

我想根据 UTC 中的日期时间计算给定时区的日期时间。

我认为我可以通过以下方式做到这一点:

DECLARE @timeUTC DATETIME = '2019-01-01 10:00:00'

SELECT 
@timeUTC AS timeUTC,
@timeUTC AT TIME ZONE 'Central European Standard Time' as at_time_zone_offset,
CONVERT(datetime, @timeUTC AT TIME ZONE 'Central European Standard Time',1) at_timezone_convert

-- OUTPUT
---timeUTC                  |at_time_zone_offset                |at_timezone_convert
---2019-01-01 10:00:00.000  |2019-01-01 10:00:00.000 +01:00     |2019-01-01 09:00:00.000

问题在于 at_timezone_convert 的结果不正确——当 UTC 时间是 10:00 时,时间 +1 是 11:00,而不是 9。

我怎样才能得到结果是 2019-01-01 11:00:00.000

【问题讨论】:

    标签: sql sql-server tsql datetime


    【解决方案1】:

    At time zone documentation 明确指出:

    inputdate 转换为目标时区中相应的 datetimeoffset 值。 当 inputdate 没有提供偏移量信息时,该函数应用时区的偏移量,假设 inputdate 在目标时区。 如果 inputdate 作为 datetimeoffset 值提供,则 AT TIME ZONE 子句将其转换使用时区转换规则进入目标时区。

    (强调我的)

    如果您将@timeUTC 声明为DateTimeOffset 而不是DateTime,您将获得不同的结果 - 另外,请注意,一旦您将DateTimeOffset 转换回DateTime,您将获得时髦的结果。

    另外,请注意yyyy-mm-dd hh:mm:ss string representation format is a localized format when working with DateTime - 新的DateTime2 数据类型并非如此,这是why you should never work with DateTime again. 的另一个原因

    DB<>Fiddle上查看演示

    【讨论】:

      【解决方案2】:

      这是我不时使用的一个技巧:

      声明@timeUTC DATETIME = '2019-01-01 10:00:00'

      选择@timeUTC 作为时间UTC,@timeUTC 在时区“UTC” AT TIME ZONE '中欧标准时间' 作为 at_time_zone_offset

      为什么会这样?您的原始日期时间没有附加偏移信息(此处的其他海报已经解释了这种情况下的默认值)第一个 at time zone 子句告诉 SQL Server“此日期时间代表 UTC 时间”并输出 datetimeoffset 数据类型.第二个at time zone 子句然后告诉它将其转换为您想要的时区。

      【讨论】:

        【解决方案3】:

        将输入作为datetimeoffset 提供,AT TIME ZONE hint 将转换为目标时区的输入。

        下面的sn-p是一个简单的例子:

        DECLARE @Utc DATETIME = '2019-01-01 10:00:00';
        DECLARE @UtcOffset datetimeoffset(7) = @Utc;
        
        SELECT 
            @Utc Utc,
            @UtcOffset UtcOffset,
            @UtcOffset AT TIME ZONE 'Central European Standard Time' UtcConverted;
        
        -- Results
        -- Utc          1/1/2019 10:00:00 AM
        -- UtcOffset    1/1/2019 10:00:00 AM +00:00
        -- UtcConverted 1/1/2019 11:00:00 AM +01:00 
        

        【讨论】:

          【解决方案4】:

          Zohar Peled 解释得很好,但以防万一,这里有一个代码示例:

          DECLARE @timeUTC DATETIME = '2019-01-01 10:00:00';
          
          SELECT
              @timeUTC AS timeUTC,
              @timeUTC AT TIME ZONE 'Central European Standard Time' as at_time_zone_offset,
              CONVERT(datetime, cast (@timeUTC AT TIME ZONE 'Central European Standard Time' as datetimeoffset),1) at_timezone_convert,
              CAST(CAST(@timeUTC AS datetimeoffset) AT TIME ZONE 'Central European Standard Time' AS datetime) AS ResultYouNeeded;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-09-29
            • 1970-01-01
            • 1970-01-01
            • 2021-09-20
            • 1970-01-01
            • 2023-01-11
            • 1970-01-01
            • 2017-08-05
            相关资源
            最近更新 更多