Как предположить, что DATETIME находится в моем местном часовом поясе, а затем преобразовать в UTC - PullRequest
2 голосов
/ 25 апреля 2019

При использовании SQL Server 2016 у меня есть столбец date_time типа DATETIME, который был вставлен с использованием местного часового пояса аппарата. Мне нужно преобразовать это значение в UTC.

Я пытался использовать

CONVERT(NVARCHAR(19), date_time AT TIME ZONE 'UTC', 127) + 'Z' AS Timestamp

но теперь я понимаю, что он автоматически предполагает, что date_time уже в UTC, поэтому преобразование не производится. Я не использую DATEADD, потому что он не учитывает DST.

Есть ли способ сообщить SQL Server, что дата и время находятся в местном часовом поясе аппарата, а затем использовать AT TIME ZONE для преобразования его в UTC?

Редактировать: это не дубликат, поскольку в комментарии в утвержденном ответе («Да, но предполагается, что время ввода UTC, что бессмысленно, если вы хотите преобразовать локальное время в UTC»), говорится о проблеме Я изложил в этом вопросе.

Ответы [ 2 ]

4 голосов
/ 25 апреля 2019

AT TIME ZONE - это половина уравнения. Другой получает часовой пояс машины, который даже в 2017 году не имеет никакой действительной функции или для SERVERPROPERTY - вам нужно покопаться в реестре.

DECLARE @TimeZone NVARCHAR(4000);
EXEC master.dbo.xp_regread 
    'HKEY_LOCAL_MACHINE', 
    'SYSTEM\CurrentControlSet\Control\TimeZoneInformation', 
    'TimeZoneKeyName', 
    @TimeZone OUT;

-- For me, that's 'W. Europe Standard Time'

SELECT {ts '2019-03-31 02:00:00' } AT TIME ZONE @TimeZone AT TIME ZONE 'UTC'
-- Yields '2019-03-31 01:00:00.000 +00:00', DST was not in effect

SELECT {ts '2019-03-31 03:00:00' } AT TIME ZONE @TimeZone AT TIME ZONE 'UTC'
-- *Also* yields '2019-03-31 01:00:00.000 +00:00', DST was in effect

Эти примеры иллюстрируют опасность преобразования меток времени, которые не были записаны с фактическими смещениями: в «сумеречной зоне» оборота летнего времени вы получаете моменты, которые по своей сути неоднозначны. Результаты таких корректировок в основном правильные, пропуская и дублируя час два раза в год. Некоторые наборы данных могут жить с этим, некоторые не могут.

1 голос
/ 25 апреля 2019

Вы просто должны указать запросу, в каком часовом поясе находится начальная дата, с предложением AT TIME ZONE после начального значения, а затем с тем, в которое вы хотите преобразовать его, со вторым предложением AT TIME ZONE после этого.

Возвращаемым значением по умолчанию является DATETIMEOFFSET, поэтому вам придется CAST/CONVERT, если вы хотите сбросить значение смещения.Я нахожусь в центральном часовом поясе США, поэтому я использовал это.Вам придется заменить правильный часовой пояс для вашего сервера.

DECLARE @date_time DATETIME = GETDATE();

SELECT 
  @date_time AT TIME ZONE 'Central Standard Time' AT TIME ZONE 'UTC' AS utc_time_as_datetimeoffset;

SELECT 
  CAST(@date_time AT TIME ZONE 'Central Standard Time' AT TIME ZONE 'UTC' AS DATETIME) AS utc_time_as_datetime;

Результаты:

+--------------------------------+
|   utc_time_as_datetimeoffset   |
+--------------------------------+
| 2019-04-25 13:29:01.057 +00:00 |
+--------------------------------+

+-------------------------+
|  utc_time_as_datetime   |
+-------------------------+
| 2019-04-25 13:29:01.057 |
+-------------------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...