Актуализиран отговор
Написах помощната програма, за която говорих в оригиналния отговор, който можете да намерите тук .
Също така, считано от SQL Server 2016 (и Azure SQL база данни), вече можете да използвате AT TIME ZONE
ключова дума за преобразуване между часови зони.
Оригинален отговор
За съжаление, няма чудесно решение за работа с часови зони в SQL Server.
Проучих обстойно проблема, който свързахте, заедно с този
също. Няма вградени функции за часова зона и каквото и да е използване на TimeZoneInfo
в SQLCLR изисква сборката да бъде регистрирана като "опасна". Това обикновено не е желателно.
Проучих и с помощта на Noda Time от SQLCLR. Можете да прочетете за това в този издание . Освен това трябваше да бъде регистриран като „опасен“ поради начина, по който някои елементи се кешират вътрешно.
В крайна сметка и при двата елемента проблемът е, че няма начин да се кешира нещо в SQLCLR. Не можете да използвате статични променливи по безопасен за нишката начин и не можете да извършвате никаква синхронизация на нишки или да използвате класове като ConcurrentDictionary
. SQL иска да има пълен контрол върху нишковидния модел на сглобката. Само еднопоточен код на стил "използване веднъж и изхвърляне" работи в "безопасни" модули. Задълбочих се в това в този въпрос:Многонишково кеширане в SQL CLR
Надяваме се, че ще има в крайна сметка да бъде компилация на Noda Time, която ще работи в SQLCLR, но ще бъде специална компилация, която не прави никакво кеширане. Така че няма да работи толкова бързо, но ще свърши работата, като същевременно е в безопасност.
TimeZoneInfo
няма вероятност да се промени. Така че освен ако екипът на SQL Server някога не въведе правилно функциите за часова зона директно в SQL Server (както правят Oracle и Postgres), тогава имате само няколко опции:
-
Не опитвайте преобразувания на часови зони в слоя данни. Работете с
datetime
илиdatetime2
стойности в UTC или използвайтеdatetimeoffset
стойности с произволно отместване. Но направете всички преобразувания между часови зони в приложния слой. Това е най-добрата ми препоръка за момента. -
Копирайте всички данни за часовите зони в действителни SQL таблици и напишете функции, които работят с тези данни. Това не е най-добрата идея, тъй като данните се променят често, така че поддръжката на таблицата може да бъде предизвикателство. Също така постигането на точни функции, включително всички правила за промени в лятното часово време, може да бъде предизвикателство. Не съм запознат с нито един проект, който да има това красиво и спретнато, но ако някой знае - моля, уведомете ме в коментарите.
-
Активирайте
xp_regread
и работете с данните за часовата зона директно от ключовете на системния регистър на Windows. Актуализациите ще бъдат направени вместо вас, но все още имате същите предизвикателства при писането на тези функции. А разрешаването на четене на системния регистър може да бъде също толкова голям риск за сигурността, колкото и разрешаването на опасни CLR сборки.
Друга идея, която обмислям, е да напиша IANA/Olson TZDB анализатор и функции специално за SQL Server. Това би било подобно на опция 2 по-горе, но направено по поддържаем начин и със стандартни данни на IANA вместо часови зони на Windows. Може би някой ден ще стигна до това или може би някой ще ме изпревари. Отново не знам за текущи проекти, които правят това, но ако някой знае за такъв, моля, уведомете ме в коментарите. (Готово - вижте актуализацията най-горе )
Относно SWITCHOFFSET
- това работи само когато вече знаете целевото отместване. Това е половината от битката и вероятно защо Microsoft все още отбелязва datetimeoffset
тъй като не е „съзнат за лятното часово време“ в документите
.