Aktualizovaná odpověď
Napsal jsem nástroj, o kterém jsem mluvil v původní odpovědi, který najdete zde .
Od SQL Server 2016 (a Azure SQL Database) můžete nyní také používat AT TIME ZONE
klíčové slovo pro převod mezi časovými pásmy.
Původní odpověď
Bohužel neexistuje žádné skvělé řešení pro práci s časovými pásmy na serveru SQL Server.
Důkladně jsem prošetřil problém, na který jste odkazoval, spolu s tímto
taky. Neexistují žádné vestavěné funkce časového pásma a jakékoli použití TimeZoneInfo
v SQLCLR vyžaduje, aby sestavení bylo registrováno jako "nebezpečné". To obvykle není žádoucí.
Zkoumal jsem také pomocí Noda Time z SQLCLR. Můžete si o tom přečíst toto vydání . Také musel být registrován jako „nebezpečný“ kvůli způsobu, jakým jsou určité položky interně ukládány do mezipaměti.
Nakonec u obou položek je problém v tom, že v SQLCLR nelze nic uložit do mezipaměti. Nemůžete používat statické proměnné způsobem bezpečným pro vlákna a nemůžete provádět žádnou synchronizaci vláken ani používat třídy jako ConcurrentDictionary
. SQL chce mít plnou kontrolu nad modelem vláken sestavy. V "bezpečných" sestavách funguje pouze jednovláknový kód stylu použití jednou a zahoď. V této otázce jsem se hlouběji zabýval:Ukládání do mezipaměti s více vlákny v SQL CLR
Doufejme, že nakonec dojde být sestavení Noda Time, které bude fungovat v SQLCLR, ale bude to speciální sestavení, které neprovádí žádné ukládání do mezipaměti. Nebude tedy fungovat tak rychle, ale svou práci zvládne a přitom bude stále v bezpečí.
TimeZoneInfo
se pravděpodobně nezmění. Takže pokud tým SQL Serveru nikdy nezavede funkce časových pásem přímo do SQL Serveru správně (jako Oracle a Postgres), pak máte jen několik možností:
-
Nepokoušejte se převádět časové pásmo v datové vrstvě. Pracujte s
datetime
nebodatetime2
hodnoty v UTC nebo použijtedatetimeoffset
hodnoty s libovolným posunem. Všechny převody mezi časovými pásmy však provádějte v aplikační vrstvě. Toto je moje nejlepší doporučení. -
Zkopírujte všechna data pro časová pásma do skutečných tabulek SQL a zapište funkce, které s těmito daty pracují. To není nejlepší nápad, protože data se často mění, takže údržba tabulky může být problém. Také získání přesných funkcí, včetně všech pravidel změny letního času, může být náročné. Nevím o žádném projektu, který by to měl pěkně a úhledně zabalené, ale pokud někdo ano, dejte mi prosím vědět v komentářích.
-
Povolit
xp_regread
a pracovat s daty časového pásma přímo z klíčů registru systému Windows. Aktualizace by byly provedeny za vás, ale stále máte stejné problémy při psaní těchto funkcí. A povolení čtení registru může být stejně tak bezpečnostní riziko jako povolení nebezpečných sestavení CLR.
Dalším nápadem, který zvažuji, je napsat IANA/Olson TZDB parser a funkce speciálně pro SQL Server. To by bylo podobné možnosti 2 výše, ale provedeno udržitelným způsobem a se standardními daty IANA namísto časových pásem Windows. Možná se k tomu někdy dostanu, nebo mě k tomu možná někdo předběhne. Opět si nejsem vědom žádného současného projektu, který by to dělal, ale pokud někdo o nějakém ví, dejte mi prosím vědět v komentářích. (hotovo – viz aktualizace nahoře )
Ohledně SWITCHOFFSET
- to funguje pouze tehdy, když již znáte cílový offset. To je polovina úspěchu a pravděpodobně proto Microsoft stále označuje datetimeoffset
v dokumentech
.