Public Class TimeInterval
Private Shared ReadOnly MILLISECONDS_TO_TICKS As Integer = 10000
Private Shared ReadOnly MILLISECONDS_IN_DAY As Integer = 864000000
Private Shared ReadOnly MILLISECONDS_IN_WEEK As Integer = 604800000
#Region "Events, internal types and structures"
Public Enum TimeIntervalType
[Single] = 0
Daily = 1
Weekly = 2
Interval = 3
End Enum
Public Event TimeIntervalPassed As EventHandler
Protected Sub OnTimeIntervalPassed(ByVal e As EventArgs)
RaiseEvent TimeIntervalPassed(Me, e)
End Sub
#End Region
#Region "Fields"
Private _type As TimeIntervalType
Private _lastDate As Date
Private _span As TimeSpan
Private WithEvents _timer As New System.Timers.Timer()
#End Region
#Region "CONSTRUCTOR"
Public Sub New()
End Sub
#End Region
#Region "Properties"
Public ReadOnly Property IntervalType() As TimeIntervalType
Get
Return _type
End Get
End Property
#End Region
#Region "Public Configuration Methods"
Public Sub SetAsSingle(ByVal dt As Date)
_type = TimeIntervalType.Single
_lastDate = dt
_span = New TimeSpan(0)
Me.StartUpTimer()
End Sub
#Region "SetAsDaily(...) overloads"
Public Sub SetAsDaily(ByVal milliseconds As Integer)
_type = TimeIntervalType.Daily
_lastDate = Nothing
_span = New TimeSpan(Math.Max(0, Math.Min(MILLISECONDS_IN_DAY, milliseconds)) * MILLISECONDS_TO_TICKS) ''864000000 == milliseconds in a day
Me.StartUpTimer()
End Sub
Public Sub SetAsDaily(ByVal seconds As Integer, ByVal milliseconds As Integer)
SetAsDaily((seconds * 1000) + milliseconds)
End Sub
Public Sub SetAsDaily(ByVal minutes As Integer, ByVal seconds As Integer, ByVal milliseconds As Integer)
SetAsDaily((minutes * 60 * 1000) + (seconds * 1000) + milliseconds)
End Sub
Public Sub SetAsDaily(ByVal hours As Integer, ByVal minutes As Integer, ByVal seconds As Integer, ByVal milliseconds As Integer)
SetAsDaily((hours * 60 * 60 * 1000) + (minutes * 60 * 1000) + (seconds * 1000) + milliseconds)
End Sub
Public Sub SetAsDaily(ByVal span As TimeSpan)
SetAsDaily(span.Milliseconds)
End Sub
#End Region
#Region "SetAsWeekly(...) overloads"
Public Sub SetAsWeekly(ByVal milliseconds As Integer)
_type = TimeIntervalType.Weekly
_lastDate = Nothing
_span = New TimeSpan(Math.Max(0, Math.Min(MILLISECONDS_IN_WEEK, milliseconds)) * MILLISECONDS_TO_TICKS) ''604800000 == milliseconds in a week
Me.StartUpTimer()
End Sub
Public Sub SetAsWeekly(ByVal seconds As Integer, ByVal milliseconds As Integer)
SetAsWeekly((seconds * 1000) + milliseconds)
End Sub
Public Sub SetAsWeekly(ByVal minutes As Integer, ByVal seconds As Integer, ByVal milliseconds As Integer)
SetAsWeekly((minutes * 60 * 1000) + (seconds * 1000) + milliseconds)
End Sub
Public Sub SetAsWeekly(ByVal hours As Integer, ByVal minutes As Integer, ByVal seconds As Integer, ByVal milliseconds As Integer)
SetAsWeekly((hours * 60 * 60 * 1000) + (minutes * 60 * 1000) + (seconds * 1000) + milliseconds)
End Sub
Public Sub SetAsWeekly(ByVal days As Integer, ByVal hours As Integer, ByVal minutes As Integer, ByVal seconds As Integer, ByVal milliseconds As Integer)
SetAsWeekly((days * 24 * 60 * 60 * 1000) + (hours * 60 * 60 * 1000) + (minutes * 60 * 1000) + (seconds * 1000) + milliseconds)
End Sub
Public Sub SetAsWeekly(ByVal span As TimeSpan)
SetAsWeekly(span.Milliseconds)
End Sub
#End Region
Public Sub SetAsInterval(ByVal start As Date, ByVal span As TimeSpan)
_type = TimeIntervalType.Interval
_lastDate = start
_span = span
Me.StartUpTimer()
End Sub
#End Region
Public Function GetNextPosition() As Date
Select Case _type
Case TimeIntervalType.Single
Return _lastDate
Case TimeIntervalType.Daily
Dim now As Date = Date.Now
_lastDate = New Date(now.Year, now.Month, now.Day)
_lastDate.AddTicks(_span.Ticks)
If _lastDate.Ticks < Date.Now.Ticks Then _lastDate.AddDays(1)
Return _lastDate
Case TimeIntervalType.Weekly
Dim now As Date = Date.Now
now.AddDays(-now.DayOfWeek)
_lastDate = New Date(now.Year, now.Month, now.Day)
_lastDate.AddTicks(_span.Ticks)
If _lastDate.Ticks < Date.Now.Ticks Then _lastDate.AddDays(1)
Return _lastDate
Case TimeIntervalType.Interval
While _lastDate.Ticks < Date.Now.Ticks
_lastDate.AddTicks(_span.Ticks)
End While
Return _lastDate
End Select
End Function
#Region "Private Timer/Event Burst"
Private _bShortChange As Boolean
Private Sub StartUpTimer()
Dim dt As Date = Me.GetNextPosition()
Dim span As TimeSpan = dt - Date.Now
Dim milli As Long = span.Ticks / MILLISECONDS_TO_TICKS
If milli < 0 Then Exit Sub
_bShortChange = (milli > MILLISECONDS_IN_DAY)
If _bShortChange Then milli = MILLISECONDS_IN_DAY
_timer.Interval = milli
_timer.Start()
End Sub
Private Sub Timer_Elapsed(ByVal sender As Object, ByVal e As EventArgs) Handles _timer.Elapsed
If Not _bShortChange Then
OnTimeIntervalPassed(New EventArgs())
End If
Me.StartUpTimer()
End Sub
#End Region
End Class