В моем пользовательском интерфейсе есть раскрывающийся список всех часовых поясов, заполненных .Net's TimeZoneInfo.GetSystemTimeZones () (в MVC Razor), который затем записывается для пользователя.
<select id="TimeZoneAbbreviation" name="TimeZoneAbbreviation">
@foreach (var tz in TimeZoneInfo.GetSystemTimeZones())
{
<!option value="@tz.StandardName" @(tz.StandardName == Model.Project.TimeZone ? "selected='selected'" : "")>@tz.DisplayName</!option>
}
</select>
У меня есть сохраненныйпроцедура, которая должна выполнить некоторую обработку и преобразовать время UTC, когда что-либо зарегистрировано в базе данных, в локальное время текущего пользователя для представления на экране.
В ходе тестирования я обнаружил, что несколько (16) часовых поясов вызывают«в часовом поясе», чтобы выдать ошибку. Эти проблемы возникают как на SQL Azure, так и на Sql Server 2016
declare @timezone as varchar(max) = 'Alaskan Standard Time'
select cast(cast(GETUTCDATE() as datetimeoffset) at time zone @timeZone as datetime) -- this works
set @timezone = 'Cabo Verde Standard Time'
select cast(cast(GETUTCDATE() as datetimeoffset) at time zone @timeZone as datetime) -- does not work
set @timezone = 'Coordinated Universal Time'
select cast(cast(GETUTCDATE() as datetimeoffset) at time zone @timeZone as datetime) -- does not work
В результате получается
(1 row affected)
Msg 9820, Level 16, State 1, Line 411
The time zone parameter 'Cabo Verde Standard Time' provided to AT TIME ZONE clause is invalid.
Msg 9820, Level 16, State 1, Line 414
The time zone parameter 'Coordinated Universal Time' provided to AT TIME ZONE clause is invalid.
Так что я обнаружил, что SQL имеет свой собственный список, который отличается от списка .Net. Поэтому немедленная мысль не использовать .Net, чтобы получить список. Скорее я должен просто спросить SQL Server через запрос.
select * from sys.time_zone_info
Проблема этого подхода заключается в том, что он возвращает другой и несовместимый список из списка .Net. В моем коде .Net у меня есть некоторый код, подобный этому
TimeZoneInfo.FromSerializedString(project.TimeZone)
Это сломается, если он использует неизвестную строку, о которой знает SQL Server.
Забавный факт # 1,В документации по https://docs.microsoft.com/en-us/sql/t-sql/queries/at-time-zone-transact-sql?view=sql-server-2017 указано, что список получен из "KEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Time Zones". Конечно же, «Всемирное координированное время» отсутствует в списке (и оно не работает). Но в списке есть «Стандартное время Кабо-Верде» (но это тоже не работает).
Забавный факт # 2, «Стандарт Кабо-Верде» не работает, но «Стандартное время Кабо-Верде» работает. Это не опечатки. Это фактические часовые пояса.
(Прежде чем кто-то спросит, я преобразовал GetUTCDate () в datetimeoffset, так как в документации сказано: «Если inputdate предоставляется как значение datetimeoffset, то предложение AT TIME ZONE преобразует его в целевое времязона, использующая правила преобразования часовых поясов. "Это то, чего я хотел добиться".
Итак, вопрос ... что мне делать? Что сделали другие? Похоже, что вся эта область - собачий завтрак.
Думаю, моя проблема в том, что у меня есть обработка часового пояса как в хранимых процессах, так и в .Net, и их обработка в часовом поясе несовместима. Я, наверное, должен как-то просто сделать одно, а не другое.
Заранее спасибо.