I want to implement time zone conversion within SQL Server 2012. However, TimeZoneInfo is marked with the MayLeakOnAbort attribute. This causes a runtime
I know the question was how to use TimeZoneInfo in a SQLCLR context, but thought I'd just add that while TimeZoneInfo is not supported (as @MattJohnson wrote elegantly), TimeZone is still available for use without the need to make the assembly unsafe.
Updated Answer
I've written the utility I spoke about in the original answer, which you can find here.
Also, as of SQL Server 2016 (and Azure SQL Database), you can now use the AT TIME ZONE
keyword to convert between time zones.
Original Answer
Unfortunately, there is no great solution for working with time zones in SQL Server.
I investigated heavily the issue you linked, along with this one also. There are no built-in time zone functions, and any use of TimeZoneInfo
in SQLCLR requires the assembly to be registered as "unsafe". This is usually not desired.
I also investigated using Noda Time from SQLCLR. You can read about it in this issue. It also had to be registered as "unsafe" because of the way certain items are cached internally.
Ultimately, with either item, the problem is that there is no way to cache anything in SQLCLR. You can't use static variables in a thread-safe manner, and you cant do any thread synchronization or use classes like ConcurrentDictionary
. SQL wants to have full control of the threading model of the assembly. Only single-threaded use-once-and-throw-away style code works in "safe" assemblies. I dug deep into this in this question: Multithreaded caching in SQL CLR
Hopefully, there will eventually be a build of Noda Time that will work in SQLCLR, but it will be a special build that doesn't do any caching. So it won't perform as quickly, but it will get the job done while still being safe.
TimeZoneInfo
isn't likely to change. So unless the SQL Server team ever brings time zone functions directly into SQL Server properly (like Oracle and Postgres do), then you've only got a few options:
Don't attempt time zone conversions in the data layer. Work with datetime
or datetime2
values in UTC, or use datetimeoffset
values with any offset. But do all conversions between time zones in the application layer. This is my best recommendation for now.
Copy all of the data for the time zones into actual SQL tables, and write functions that work with that data. This isn't the best idea, because the data changes often so table maintenance can be a challenge. Also getting the functions accurate, including all of the rules of daylight saving changes, can be challenging. I am not aware of any project that has this bundled up nice and neat, but if anyone is - then please let me know in comments.
Enable xp_regread
and work with the timezone data directly from the windows registry keys. Updates would be done for you, but you still have the same challenges in writing these functions. And enabling registry reads might be just as much of a security risk as enabling unsafe CLR assemblies anyway.
Another idea I am considering is to write an IANA/Olson TZDB parser and functions specifically for SQL Server. This would be similar to option 2 above, but done in a maintainable way, and with IANA standard data instead of Windows time zones. Maybe I'll get to this someday, or maybe someone will beat me to it. Again, I am not aware of any current project that does this, but if someone knows of one, please let me know in comments. (done - see update at top)
Regarding SWITCHOFFSET
- that only works when you already know the target offset. That's half the battle, and probably why Microsoft still marks datetimeoffset
as not "daylight savings aware" in the docs.