You can easily do this with a CLR Stored Procedure.
[SqlFunction]
public static SqlDateTime ToLocalTime(SqlDateTime UtcTime, SqlString TimeZoneId)
{
if (UtcTime.IsNull)
return UtcTime;
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneId.Value);
return new SqlDateTime(TimeZoneInfo.ConvertTimeFromUtc(UtcTime.Value, timeZone));
}
You can store the available TimeZones in a table:
CREATE TABLE TimeZones
(
TimeZoneId NVARCHAR(32) NOT NULL CONSTRAINT PK_TimeZones PRIMARY KEY,
DisplayName NVARCHAR(64) NOT NULL,
SupportsDaylightSavingTime BIT NOT NULL,
)
And this stored procedure will fill the table with the possible time zones on your server.
public partial class StoredProcedures
{
[SqlProcedure]
public static void PopulateTimezones()
{
using (var sql = new SqlConnection("Context Connection=True"))
{
sql.Open();
using (var cmd = sql.CreateCommand())
{
cmd.CommandText = "DELETE FROM TimeZones";
cmd.ExecuteNonQuery();
cmd.CommandText = "INSERT INTO [dbo].[TimeZones]([TimeZoneId], [DisplayName], [SupportsDaylightSavingTime]) VALUES(@TimeZoneId, @DisplayName, @SupportsDaylightSavingTime);";
var Id = cmd.Parameters.Add("@TimeZoneId", SqlDbType.NVarChar);
var DisplayName = cmd.Parameters.Add("@DisplayName", SqlDbType.NVarChar);
var SupportsDaylightSavingTime = cmd.Parameters.Add("@SupportsDaylightSavingTime", SqlDbType.Bit);
foreach (var zone in TimeZoneInfo.GetSystemTimeZones())
{
Id.Value = zone.Id;
DisplayName.Value = zone.DisplayName;
SupportsDaylightSavingTime.Value = zone.SupportsDaylightSavingTime;
cmd.ExecuteNonQuery();
}
}
}
}
}