Перенос SQL хранимых значений DateTime в наилучшую практику DateTimeOffset?

Учитывая таблицу SQL с столбцом DateTime и приблизительно 100 тыс. строк различных дат (значения локального времени PST) за последние 3 года, какова наилучшая стратегия для переноса этих значений столбцов на DateTimeOffset, чтобы "добавить" отсутствующую информацию об утере tz tz?

Существующие значения DateTime сохраняются без каких-либо данных о смещении часового пояса /utc. Сохраненные даты всегда представляют собой Pacific Time (-800 или -700 в зависимости от летнего времени). Цель состоит в том, чтобы ретроактивно добавить смещение tz ко всем существующим данным с предположением, что дата была получена из тихоокеанского времени (независимо от правильного смещения в момент, указанный в дате).

  • В SQL лучше всего подходит для такого типа миграции без потери данных или изменения существующих значений?

  • Переходя к следующему шагу, каков наиболее эффективный метод миграции всей базы данных с умеренным размером (~ 100 гб в ~ 100 таблицах с 2 столбцами DateTime для таблицы) для использования столбцов и значений DateTimeOffset?

  • Что происходит с данными, которые были зарегистрированы во время/в течение 2 часов в дате переключения PST/PDT? Есть ли потеря данных?

SQL Server 2008 + С# 4.5

Если это неправильная область, пожалуйста, укажите мне в правильном направлении, спасибо!

Изменить: Yay, время баунти.

Ответ 1

Летнее время - не всегда точная наука. Например. в течение периода, используемого в Северной Америке, было изменено правило в 2007 году. По этой причине предлагалось бы заполнить таблицу соответствующими датами. Например. на 2000-2013 годы:

-- Populate a table with PST daylight saving start/end times
-- Example data for 2000-2013 - sourced from
-- http://www.timeanddate.com/worldclock/timezone.html?n=137
CREATE TABLE dst (start DateTime, [end] DateTime);
INSERT INTO dst (start, [end]) VALUES ('02:00 2 Apr 2000', '02:00 29 Oct 2000');
INSERT INTO dst (start, [end]) VALUES ('02:00 1 Apr 2001', '02:00 28 Oct 2001');
INSERT INTO dst (start, [end]) VALUES ('02:00 7 Apr 2002', '02:00 27 Oct 2002');
INSERT INTO dst (start, [end]) VALUES ('02:00 6 Apr 2003', '02:00 26 Oct 2003');
INSERT INTO dst (start, [end]) VALUES ('02:00 4 Apr 2004', '02:00 31 Oct 2004');
INSERT INTO dst (start, [end]) VALUES ('02:00 3 Apr 2005', '02:00 30 Oct 2005');
INSERT INTO dst (start, [end]) VALUES ('02:00 2 Apr 2006', '02:00 29 Oct 2006');
INSERT INTO dst (start, [end]) VALUES ('02:00 11 Apr 2007', '02:00 4 Oct 2007');
INSERT INTO dst (start, [end]) VALUES ('02:00 9 Apr 2008', '02:00 2 Nov 2008');
INSERT INTO dst (start, [end]) VALUES ('02:00 8 Apr 2009', '02:00 1 Nov 2009');
INSERT INTO dst (start, [end]) VALUES ('02:00 14 Apr 2010', '02:00 7 Nov 2010');
INSERT INTO dst (start, [end]) VALUES ('02:00 13 Apr 2011', '02:00 6 Nov 2011');
INSERT INTO dst (start, [end]) VALUES ('02:00 11 Apr 2012', '02:00 4 Nov 2012');
INSERT INTO dst (start, [end]) VALUES ('02:00 10 Apr 2013', '02:00 3 Nov 2013');

Конечно, вам может понадобиться лот больше, чем это - оставит это как упражнение для читателя:-)

Итак, скажем, вы заполнили приведенную выше таблицу всем возможным диапазоном, и у вас есть дата/время в поле dt таблицы test. Затем вы можете присоединиться к приведенной выше таблице и сделать такие преобразования следующим образом:

-- Convert sample dates to PST offset with daylight saving where appropriate
SELECT test.dt,
       CAST(CONVERT(VARCHAR(23), test.dt, 126) + -- Convert to ISO8601 format
            CASE WHEN dst.start IS NULL
                 THEN '-08:00' -- No record joined so not within DST period
                 ELSE '-07:00' -- DST record joined so is within DST period
            END AS DateTimeOffset) AS dto
FROM test
LEFT JOIN dst -- Join on daylight savings table to find out whether DST applies
ON test.dt >= dst.start
AND test.dt <= dst.[end]

Здесь демонстрационная версия скрипта SQL.

Ответ 2

SQL Server 2016 представил синтаксис T-SQL AT TIME ZONE для решения этих проблем.

Итак, если вы знаете часовой пояс данных, вы можете добавить смещение с помощью простого изменения и обновления script, как показано ниже (при условии, что у вас есть таблица с именем MyTable с столбцом datetime2 с именем DateTimeColumn):

alter table MyTable 
   alter column DateTimeColumn datetimeoffset;

update Mytable
   set DateTimeColumn = convert(datetime2, DateTimeColumn) AT TIME ZONE 'Pacific Standard Time' 

Рассматривается переход на летнее время (DST) и не должно быть потерь данных.

(Я знаю, что OP задал SQL Server 2008, и вопрос был задан и дан ответ давно, но, надеюсь, кому-то, кто в настоящее время борется с такой же проблемой, поможет этот ответ.)