简体   繁体   English

从UTC时间计算特定时区的时间

[英]Calculate time at specific Timezone, from UTC Time

I want to calculate Datetime at given timezone based on Datetime in UTC.我想根据UTC中的日期时间计算给定时区的日期时间。

I thought that I can do it with the following:我认为我可以通过以下方式做到这一点:

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

The problem is that result of at_timezone_convert is incorrect- when at UTC time is 10:00, then time +1 is 11:00, not 9.问题是 at_timezone_convert 的结果不正确——当 UTC 时间是 10:00 时,那么时间 +1 是 11:00,而不是 9。

How can I get the result to be 2019-01-01 11:00:00.000 ?我怎样才能得到结果是2019-01-01 11:00:00.000

At time zone documentation clearly states: At time zone文档中明确指出:

Converts an inputdate to the corresponding datetimeoffset value in the target time zone.inputdate转换为目标时区中相应的 datetimeoffset 值。 When inputdate is provided without offset information, the function applies the offset of the time zone assuming that inputdate is in the target time zone.当 inputdate 提供而没有偏移信息时,函数会应用时区的偏移量,假设 inputdate 在目标时区。 If inputdate is provided as a datetimeoffset value, then AT TIME ZONE clause converts it into the target time zone using the time zone conversion rules.如果 inputdate 作为 datetimeoffset 值提供,则 AT TIME ZONE 子句使用时区转换规则将其转换为目标时区。

(emphasis mine) (强调我的)

If you'll declare @timeUTC as DateTimeOffset and not as DateTime you'll get different results - also, note that once you've converted the DateTimeOffset back to DateTime you'll get funky results.如果您将@timeUTC声明为DateTimeOffset而不是DateTime您将获得不同的结果 - 另外,请注意,一旦您将DateTimeOffset转换回DateTime您将获得时髦的结果。

Also, please note that the yyyy-mm-dd hh:mm:ss string representation format is a localized format when working with DateTime - that is not the case with the newer DateTime2 data type, which is one more reason why you should never work with DateTime again.另外,请注意yyyy-mm-dd hh:mm:ss字符串表示格式在使用DateTime时是一种本地化格式- 较新的DateTime2数据类型并非如此,这是您不应该工作的另一个原因再次使用DateTime

See a demo on DB<>Fiddle查看DB<>Fiddle上的演示

Supplying the input as a datetimeoffset the AT TIME ZONE hint will convert to the input to the target time zone.将输入作为datetimeoffsetAT TIME ZONE提示将转换为目标时区的输入。

The snippet below is a simple example:下面的代码片段是一个简单的例子:

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 

Here's a trick I use from time to time:这是我不时使用的一个技巧:

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

SELECT @timeUTC AS timeUTC, @timeUTC AT TIME ZONE 'UTC' AT TIME ZONE 'Central European Standard Time' as at_time_zone_offset SELECT @timeUTC AS timeUTC, @timeUTC AT TIME ZONE 'UTC' AT TIME ZONE '中欧标准时间' as at_time_zone_offset

Why does this work?为什么这样做? Your original datetime has no offset information attached to it (other posters here have explained what the default is when this is the case) The first at time zone clause tells SQL Server "this datetime represents a time in UTC" and outputs a datetimeoffset data type.您的原始日期时间没有附加偏移信息(这里的其他海报已经解释了这种情况下的默认值)第一个at time zone子句告诉 SQL Server“此日期时间表示 UTC 时间”并输出 datetimeoffset 数据类型. The second at time zone clause then tells it to convert it to your desired time zone.然后第二个at time zone子句告诉它把它转换成你想要的时区。

Zohar Peled explained it just fine, but just in case, here is a code example: 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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM