Я подозреваю, что у вас есть проблемы часовой пояс, то есть вы сохранили datetime
значения, предполагая, EST, но теперь должны возвращать значения для ваших клиентов, используя UTC. Добавление смещения ко всем возвращаемым значениям здесь не поможет, потому что в какой-то момент вам, возможно, придется поддерживать другой часовой пояс или ввести время в PST, которое также должно появиться в UTC и т. Д. Не говоря уже о том, что в течение лета смещение будет должны быть заменены на 1 час
Единственным надежным решением является использование типа datetimeoffset вместо datetime
. Этот тип напрямую соответствует типу DateTimeOffset в .NET и сохраняет смещение часового пояса вместе со значениями даты и времени. Сравнения между моментами времени в разных часовых поясах возможны, поэтому вам не придется беспокоиться о сортировке, индексация и т.д.
Кастинг datetimeoffset
к datetime
или datetime2
преобразует время в местное время, т.е. в часовом поясе сервера. Это означает, что вы должны быть осторожны, чтобы преобразовать все виды использования datetime
в datetimeoffset
, если вам не нужны неожиданные конверсии.
Вы можете преобразовать datetimeoffset
в UTC или местного времени с помощью метода CONVERT
с параметром типа, например:
convert(datetime2,SYSDATETIMEOFFSET (),1)
возвратит datetime
в UTC, а
convert(datetime2,SYSDATETIMEOFFSET (),0)
преобразует значение до местного времени
Чтобы преобразовать существующие даты в datetimeoffset
, вы должны использовать TODATETIMEOFFSET функция, указав текущую временную зону, например:
select todatetimeoffset(getdate(),-300)
или
select todatetimeoffset(getdate(),'-05:00')
Как для преобразования существующих данных в datetimeoffset
, это немного сложно из-за перехода на летнее время. Вы должны проверить фактическую дату, чтобы решить, какое смещение применять во время преобразования.
Изменение типа таблицы
Изменение самого типа легко:
alter table MyTable ALTER COLUMN col1 datetimeoffset NOT NULL
Это будет конвертировать все существующие значения на значения UTC с тем же время, как исходные значения, только с 00:00
смещение.
Вы можете изменить смещение с SWITCHOFFSET
но не применить его к каждой строке с:
UPDATE MyTable
Set col1=SWITCHOFFSET(col,'-05:00') @@garbled-to-prevent-copying
Вы должны проверить дату и применить правильное смещение. Правила меняются из страны в страну или даже из года в год. В последнее десятилетие Россия должна была изменить правила как минимум 3 раза.
Вместо расчета даты нужно и использовать:
UPDATE MyTable
Set col1=SWITCHOFFSET(col,'-05:00')
where col1 between '2014....' and '2014....' or
col1 between '2013....' and '2013....' ...
UPDATE MyTable
Set col1=SWITCHOFFSET(col,'-06:00')
where col1 between '2014....' and '2014....' or
col1 between '2013....' and '2013....' ...
Еще один обновление
Это может быть проще заранее рассчитать изменение даты перехода на летнее время с библиотекой как Noda Time и хранить их в вспомогательная таблица. Это изменит вычисление смещения до простой операции поиска.
Noda Time (и другие подобные библиотеки) используют Timezone database, поддерживаемый IANA, который содержит часовые пояса и правила DST для ... Я думаю, что навсегда. База данных (и соответствующие библиотеки) регулярно обновляется.
Вы посмотрели на создание представления, которое инкапсулирует 'DATEADD' и использует это как ваш источник для запросов? –
Вы можете использовать [вычисленные столбцы] (https://msdn.microsoft.com/en-us/library/ms188300.aspx). Однако тогда вы будете вычислять его при каждом выборе, если вы не укажете 'PERSISTED'. Поэтому я бы предпочел 'AFTER INSERT trigger' или вычислить его там, где мне это нужно, с помощью' SELECT'. –
Какую реальную проблему вы пытаетесь решить? Почему вы хотите, чтобы SQL Server возвращал магические значения, которые не хранятся в базе данных?Как бы вы обновили данные, если его значение было волшебным образом изменено на 5 часов? У вас проблемы с часовым поясом? –