简体   繁体   中英

Calculate time at specific Timezone, from UTC Time

I want to calculate Datetime at given timezone based on Datetime in 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.

How can I get the result to be 2019-01-01 11:00:00.000 ?

At time zone documentation clearly states:

Converts an inputdate to the corresponding datetimeoffset value in the target time zone. 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. 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.

(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.

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.

See a demo on DB<>Fiddle

Supplying the input as a datetimeoffset the AT TIME ZONE hint will convert to the input to the target 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'

SELECT @timeUTC AS timeUTC, @timeUTC AT TIME ZONE 'UTC' AT TIME ZONE 'Central European Standard Time' 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. The second at time zone clause then tells it to convert it to your desired time zone.

Zohar Peled explained it just fine, but just in case, here is a code example:

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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