Ever wondered how the hell you can have a ‘live’ timezone which understands its own daylight savings rules and handles localization without having to use .Net globalization?
The usual circumstance where this problem manifests itself is when deploying time sensitive applications on web servers. If you can store some simple timezone region info (a timezone label) for each user then you can perform locale agnostic conversions for the user as long as you store all your times as UTC… Just look up the label and use the TimeZoneFactory to create your timezone.
Use an XML datafile to popultate the TimeZone objects through the Factory. You can even have a RealTimeZone ListItemCollection helper for binding a list of RealTimeZones to a combo box.
Here is the core class without the creation factories – (ie: this is the hard part!):
Public Class RealTimeZone
Inherits System.TimeZone
Private Sub New()
End Sub
Private _GenericName As String
Private _DaylightOffset As Integer
Private _StandardOffset As Integer
Private _DaylightStartMonthUTC As Integer
Private _DaylightStartDayUTC As Integer
Private _DaylightStartHourUTC As Integer
Private _DaylightEndMonthUTC As Integer
Private _DaylightEndDayUTC As Integer
Private _DaylightEndHourUTC As Integer
Private _DaylightName As String
Private _StandardName As String
Protected Friend Sub New(ByVal GenericName As String, ByVal DaylightOffset As Integer, ByVal StandardOffset As Integer, ByVal DaylightStartMonthUTC As Integer, ByVal DaylightStartDayUTC As Integer, ByVal DaylightStartHourUTC As Integer, ByVal DaylightEndMonthUTC As Integer, ByVal DaylightEndDayUTC As Integer, ByVal DaylightEndHourUTC As Integer, ByVal DaylightName As String, ByVal StandardName As String)
Me._GenericName = GenericName
Me._DaylightOffset = DaylightOffset
Me._StandardOffset = StandardOffset
Me._DaylightStartMonthUTC = DaylightStartMonthUTC
Me._DaylightStartDayUTC = DaylightStartDayUTC
Me._DaylightStartHourUTC = DaylightStartHourUTC
Me._DaylightEndMonthUTC = DaylightEndMonthUTC
Me._DaylightEndDayUTC = DaylightEndDayUTC
Me._DaylightEndHourUTC = DaylightEndHourUTC
Me._DaylightName = DaylightName
Me._StandardName = StandardName
End Sub
Public ReadOnly Property GenericName() As String
Get
Return Me._GenericName
End Get
End Property
Public Function RenderLocalTime(ByVal UTCTime As DateTime, ByVal timeFormat As String) As String
Dim ot As DateTime = UTCTime.AddHours(GetUtcOffset(UTCTime).TotalHours)
Return ot.ToString(timeFormat)
End Function
Public Function ConvertToLocalTime(ByVal SourceUniversalTime As DateTime) As DateTime
Return SourceUniversalTime.AddHours(GetUtcOffset(SourceUniversalTime).TotalHours)
End Function
Public Function ConvertFromLocalTime(ByVal SourceLocalTime As DateTime) As DateTime
Return SourceLocalTime.AddHours((GetUtcOffset(SourceLocalTime).TotalHours * -1))
End Function
Public Function GetUTCDayStart(ByVal Year As Integer, ByVal Month As Integer, ByVal Day As Integer) As DateTime
Dim target As New DateTime(Year, Month, Day, 0, 0, 0)
Return ConvertFromLocalTime(target)
End Function
Public Function GetUTCDayEnd(ByVal Year As Integer, ByVal Month As Integer, ByVal Day As Integer) As DateTime
Dim target As New DateTime(Year, Month, Day, 23, 59, 59)
Return ConvertFromLocalTime(target)
End Function
Public Function GetUTCDayStart(ByVal LocalDate As DateTime) As DateTime
Dim target As New DateTime(LocalDate.Year, LocalDate.Month, LocalDate.Day, 0, 0, 0)
Return ConvertFromLocalTime(target)
End Function
Public Function GetUTCDayEnd(ByVal LocalDate As DateTime) As DateTime
Dim target As New DateTime(LocalDate.Year, LocalDate.Month, LocalDate.Day, 23, 59, 59)
Return ConvertFromLocalTime(target)
End Function
Public Overrides Function GetDaylightChanges(ByVal year As Integer) As System.Globalization.DaylightTime
Dim sdUTC As New DateTime(year, Me.DaylightStartMonthUTC, Me.DaylightStartDayUTC, Me.DaylightStartHourUTC, 0, 0)
Dim edUTC As New DateTime(year, Me.DaylightEndMonthUTC, Me.DaylightEndDayUTC, Me.DaylightEndHourUTC, 0, 0)
Return New System.Globalization.DaylightTime(System.TimeZone.CurrentTimeZone.ToLocalTime(sdUTC), System.TimeZone.CurrentTimeZone.ToLocalTime(edUTC), New TimeSpan(1, 0, 0))
End Function
Public Overloads Overrides Function GetUtcOffset(ByVal time As Date) As System.TimeSpan
Dim dt As System.Globalization.DaylightTime = GetDaylightChanges(time.Year)
Dim cmpStart As Integer = time.CompareTo(dt.Start)
Dim cmpEnd As Integer = time.CompareTo(dt.End)
If (cmpStart >= 0) And (cmpEnd Return New TimeSpan(Me.StandardOffset, 0, 0)
End Function
Public Overloads Function GetUtcOffset() As System.TimeSpan
Return GetUtcOffset(DateTime.UtcNow)
End Function
Public ReadOnly Property DaylightOffset() As Integer
Get
Return Me._DaylightOffset
End Get
End Property
Public ReadOnly Property StandardOffset() As Integer
Get
Return Me._StandardOffset
End Get
End Property
Public ReadOnly Property DaylightStartMonthUTC() As Integer
Get
Return Me._DaylightStartMonthUTC
End Get
End Property
Public ReadOnly Property DaylightStartDayUTC() As Integer
Get
Return Me._DaylightStartDayUTC
End Get
End Property
Public ReadOnly Property DaylightStartHourUTC() As Integer
Get
Return Me._DaylightStartHourUTC
End Get
End Property
Public ReadOnly Property DaylightEndMonthUTC() As Integer
Get
Return Me._DaylightEndMonthUTC
End Get
End Property
Public ReadOnly Property DaylightEndDayUTC() As Integer
Get
Return Me._DaylightEndDayUTC
End Get
End Property
Public ReadOnly Property DaylightEndHourUTC() As Integer
Get
Return Me._DaylightEndHourUTC
End Get
End Property
Public Overrides ReadOnly Property DaylightName() As String
Get
Return Me._DaylightName
End Get
End Property
Public Overrides ReadOnly Property StandardName() As String
Get
Return Me._StandardName
End Get
End Property
End Class
Filed under: Uncategorized