Zaktualizowana odpowiedź
Napisałem narzędzie, o którym mówiłem w oryginalnej odpowiedzi, które można znaleźć tutaj .
Ponadto, począwszy od SQL Server 2016 (i Azure SQL Database), można teraz używać AT TIME ZONE
słowo kluczowe do konwersji między strefami czasowymi.
Oryginalna odpowiedź
Niestety nie ma świetnego rozwiązania do pracy ze strefami czasowymi w SQL Server.
Dokładnie zbadałem problem, który połączyłeś, wraz z tym
Również. Nie ma wbudowanych funkcji stref czasowych i każde użycie TimeZoneInfo
w SQLCLR wymaga, aby zestaw był zarejestrowany jako „niebezpieczny”. Zwykle nie jest to pożądane.
Badałem również za pomocą Noda Time z SQLCLR. Możesz o tym przeczytać w tym numerze . Musiał również zostać zarejestrowany jako „niebezpieczny” ze względu na sposób, w jaki niektóre elementy są wewnętrznie buforowane.
Ostatecznie w przypadku obu pozycji problem polega na tym, że nie ma możliwości buforowania czegokolwiek w SQLCLR. Nie można używać zmiennych statycznych w sposób bezpieczny dla wątków i nie można wykonywać żadnej synchronizacji wątków ani używać klas takich jak ConcurrentDictionary
. SQL chce mieć pełną kontrolę nad modelem wątków zestawu. Tylko jednowątkowy kod stylu jednorazowego użytku i wyrzucania działa w zestawach „bezpiecznych”. Zagłębiłem się w to w tym pytaniu:Wielowątkowe buforowanie w SQL CLR
Mamy nadzieję, że w końcu być kompilacją Noda Time, która będzie działać w SQLCLR, ale będzie to specjalna kompilacja, która nie wykonuje żadnego buforowania. Więc nie będzie działać tak szybko, ale wykona zadanie, zachowując bezpieczeństwo.
TimeZoneInfo
prawdopodobnie się nie zmieni. Tak więc, o ile zespół SQL Server nigdy nie wprowadzi prawidłowo funkcji stref czasowych bezpośrednio do SQL Server (tak jak robią to Oracle i Postgres), masz tylko kilka opcji:
-
Nie próbuj konwersji strefy czasowej w warstwie danych. Pracuj z
datetime
lubdatetime2
wartości w UTC lub użyjdatetimeoffset
wartości z dowolnym przesunięciem. Ale wykonaj wszystkie konwersje między strefami czasowymi w warstwie aplikacji. Na razie to moja najlepsza rekomendacja. -
Skopiuj wszystkie dane dla stref czasowych do rzeczywistych tabel SQL i zapisz funkcje, które działają z tymi danymi. To nie jest najlepszy pomysł, ponieważ dane często się zmieniają, więc utrzymanie tabeli może być wyzwaniem. Również uzyskanie dokładnych funkcji, w tym wszystkich zasad zmian czasu letniego, może być trudne. Nie znam żadnego projektu, który by to spakował ładnie i schludnie, ale jeśli ktoś jest - daj mi znać w komentarzach.
-
Włącz
xp_regread
i pracować z danymi strefy czasowej bezpośrednio z kluczy rejestru systemu Windows. Aktualizacje zostałyby wykonane za Ciebie, ale nadal masz te same wyzwania związane z pisaniem tych funkcji. A włączenie odczytów rejestru może być tak samo zagrożeniem dla bezpieczeństwa, jak włączenie niebezpiecznych zestawów CLR.
Innym pomysłem, który rozważam, jest napisanie IANA/Olson TZDB parser i funkcje specjalnie dla SQL Server. Byłoby to podobne do powyższej opcji 2, ale zrobione w sposób możliwy do utrzymania i ze standardowymi danymi IANA zamiast stref czasowych systemu Windows. Może kiedyś do tego dojdę, a może ktoś mnie do tego przebije. Znowu nie znam żadnego obecnego projektu, który to robi, ale jeśli ktoś zna taki, daj mi znać w komentarzach. (gotowe – patrz aktualizacja u góry )
Odnośnie SWITCHOFFSET
- to działa tylko wtedy, gdy znasz już docelowe przesunięcie. To połowa sukcesu i prawdopodobnie dlatego Microsoft nadal zaznacza datetimeoffset
jako nie „świadomość czasu letniego” w dokumentacji
.