Solved

# Calculating an interval of time

Posted on 2008-06-16
1,956 Views
Hi all,

i need to figure out how to calculate an interval of time - in ms.
I am working on a backup project that the user will run, select the date and time of the next run and then start the program.
This program will run on that day and time, then reset and run again the same day and time the next week.

For example, the user starts the program on Monday, at 11:24 am.
They select Friday, at 20:30 (8:30 pm) and start the program.  The code below calculates the number of ms for the interval of the System.Timers.Timer
Friday at 20:30 comes, the program runs and resets itself to run the next friday at 20:30 (recalculating the new interval)

what i'm needing to calculate is the interval from when the user clicks 'start' until the program actually runs.

What I have so far is
2 combo-boxes
(DayBox)  with Sunday-Saturday, so that the indecies of the combobox correspond with Date.DayOfWeek values, ie Sunday=0, Monday=1, etc)

(TimeBox) with times (in 24h format, in 30 minute increments - ie 00:00, 00:30, 01:00 ...... 23:00,23:30)

The following code seems to work, but after writing it, it seems very cumbersome.
Does anyone have a simpler, or more elegant way to do this?

``````Private Enum MSeconds
Days = 86400000
Hours = 3600000
Minutes = 60000
Seconds = 1000
End Enum

Private Function GetNextInterval() As Long
Dim day As Integer = Now.DayOfWeek
Dim day2 As Integer = DayBox.SelectedIndex
Dim d As Integer = 0
Dim h As Integer = CInt(Split(TimeBox.Text, ":")(0))
Dim m As Integer = CInt(Split(TimeBox.Text, ":")(1))
Dim s As Integer = 0
' number of days til next backup
If day > day2 Then
' if today is past backup day
d = 7 - (day - day2)
ElseIf day2 > day Then
d = day2 - day
Else
'day=day2
Dim time As New Date(Now.Year, Now.Month, Now.Day, h, m, s)
Dim ts As TimeSpan = time - Now
If ts.TotalMilliseconds > 0 Then
d = 6
Else
d = 0
End If
End If

' number of hours
If h = 0 Then
' use 24
If Now.Hour = 0 Then
h = 0
Else
h = 24 - Now.Hour
End If
Else
If h > Now.Hour Then
h = h - Now.Hour
ElseIf h < Now.Hour Then
h = 24 - (Now.Hour - h)
Else
h = 0
End If
End If
' number of minutes
If m = 0 Then
' use 60
If m = Now.Minute Then
m = 0
Else
m = 60 - m
End If
ElseIf m = 30 Then
If m > Now.Minute Then
m = 30 - Now.Minute
Else
m = 60 - (Now.Minute - m)
End If
End If
' number of secods - leave at 0
s = 0
Return d * MSeconds.Days + h * MSeconds.Hours + m * MSeconds.Minutes + s * MSeconds.Seconds
End Function
``````
0
Question by:sgaggerj
• 3
• 3
• 2
• +1

LVL 18

Expert Comment

ID: 21794819
Don't use a timer for this.  Set up a windows scheduled task instead.

But if you absolutely must use a timer, you're making this way too hard.  Just return the ts.TotalMilliseconds that you calculated at the top.
0

LVL 7

Assisted Solution

orcic earned 75 total points
ID: 21794908
I agree with jcoehoorn. Your simplified function would be something like....

Private Function GetNextInterval() As Long
Dim day As Integer = Now.DayOfWeek
Dim day2 As Integer = DayBox.SelectedIndex
Dim d As Integer = 0
Dim h As Integer = CInt(Split(TimeBox.Text, ":")(0))
Dim m As Integer = CInt(Split(TimeBox.Text, ":")(1))
Dim s As Integer = 0
' number of days til next backup
If day > day2 Then
' if today is past backup day
d = 7 - (day - day2)
ElseIf day2 > day Then
d = day2 - day
Else
'day=day2
Dim time As New Date(Now.Year, Now.Month, Now.Day, h, m, s)
Dim ts As TimeSpan = time - Now
If ts.TotalMilliseconds > 0 Then
d = 6
Else
d = 0
End If
End If
Dim time1 As New Date(Now.Year, Now.Month, Now.Day+d, h, m, s)
Dim ts1 As TimeSpan = time1 - Now
Return ts1.TotalMilliseconds
End Function
0

LVL 7

Expert Comment

ID: 21794978
replace
Dim time1 As New Date(Now.Year, Now.Month, Now.Day+d, h, m, s)
with
Dim time1 As Date

0

LVL 1

Author Comment

ID: 21795831
I think it should also be
Dim ts1 as TimeSpan
if (Now-time1).totalmilliseconds > 0 then
ts1=now-time1
else
ts1=time1-now
endif

otherwise it could return a negative value, right?

that's why i used
Dim l As Long = d * MSeconds.Days + h * MSeconds.Hours + m * MSeconds.Minutes + s * MSeconds.Seconds
so it would always be a positive value

however, i just ran a couple other tests and it doesn't seem to be working right.

If I have it start Monday, at 15:00 (now it's currently 13:20), it comes up with 6 days, 2 hours, etc etc.
it should only be 1 hour 40 minutes
because Monday at 3pm hasn't arrived yet.

``````Private Function GetNextInterval() As Long
Dim day As Integer = Now.DayOfWeek
Dim day2 As Integer = DayBox.SelectedIndex
Dim d As Integer = 0
Dim h As Integer = CInt(Split(TimeBox.Text, ":")(0))
Dim m As Integer = CInt(Split(TimeBox.Text, ":")(1))
Dim s As Integer = 0
' number of days til next backup
If day > day2 Then
' if today is past backup day
d = 7 - (day - day2)
ElseIf day2 > day Then
d = day2 - day
Else
'day=day2
Dim time As New Date(Now.Year, Now.Month, Now.Day, h, m, s)
If time > Now Then
d = 0
Else
d = 6
End If
'Dim ts As TimeSpan = time - Now
'If ts.TotalMilliseconds > 0 Then
'    d = 6
'Else
'    d = 0
'End If
End If

' number of hours
If h = 0 Then
' use 24
If Now.Hour = 0 Then
h = 0
Else
h = 24 - Now.Hour
End If
Else
If h > Now.Hour Then
h = h - Now.Hour
ElseIf h < Now.Hour Then
h = 24 - (Now.Hour - h)
Else
h = 0
End If
End If
' number of minutes
If m = 0 Then
' use 60
If m = Now.Minute Then
m = 0
Else
' CHANGED HERE FROM m=60-m and added h-=1
m = 60 - Now.Minute
h -= 1
End If
ElseIf m = 30 Then
If m > Now.Minute Then
m = 30 - Now.Minute
Else
m = 60 - (Now.Minute - m)
End If
End If
' number of secods - leave at 0
s = 0

Dim time1 As New Date
Dim ts1 As TimeSpan
If (time1 - Now).TotalMilliseconds > 0 Then
ts1 = time1 - Now
Else
ts1 = Now - time1
End If
Return ts1.TotalMilliseconds
End Function
``````
0

LVL 85

Accepted Solution

Mike Tomlinson earned 425 total points
ID: 21796008
Good grief...you waaaaaaaaaay overcomplicated it:
``````    Private Function GetNextInterval() As Long
Dim h As Integer = CInt(Split(TimeBox.Text, ":")(0))
Dim m As Integer = CInt(Split(TimeBox.Text, ":")(1))
Dim dtBase As DateTime = DateTime.Now.AddDays(DayBox.SelectedIndex - DateTime.Now.DayOfWeek)
Dim dtTarget As New DateTime(dtBase.Year, dtBase.Month, dtBase.Day, h, m, 0)
If dtTarget < DateTime.Now Then
End If
Return dtTarget.Subtract(DateTime.Now).TotalMilliseconds
End Function
``````
0

LVL 18

Expert Comment

ID: 21796013
One thing to remember:  Now is a very dynamic value, so this code is fatally flawed:
Dim ts1 as TimeSpan
if (Now-time1).totalmilliseconds > 0 then
ts1=now-time1
else
ts1=time1-now
endif

This would be more correct:
``````Dim ts1 as TimeSpan
Dim curTime As Date = Now
if (curTime - time1).totalmilliseconds > 0 then
ts1=curTime - time1
else
ts1=time1 - curTime
endif
``````
0

LVL 1

Author Comment

ID: 21796789
heheh 'good grief'.  Yea I know I have a wierd way of looking at things!

That's pretty much what i was looking for Idle...

i came up with something a little different

DayBox as DateTimePicker

then

Private Function GetNextInterval() As Long
Dim DayToRun As Date = DayBox.Value
Dim TargetDate As Date = New Date(DayToRun.Year, DayToRun.Month, DayToRun.Day, CInt(Split(TimeBox.Text, ":")(0)), CInt(Split(TimeBox.Text, ":")(1)), 0)

Dim ts As TimeSpan
If TargetDate > Now Then
ts = TargetDate - Now
Else
ts = Now - TargetDate
End If
Return ts.TotalMilliseconds
End Function

though changing my if/then statement to be more like jcoehoorn's would probably be better.

I thought I was going to be able to gloat and say my solution had less lines than Idle_Mind's ..... waaahh!

Thanks guys!

0

LVL 85

Expert Comment

ID: 21796892
I wouldn't say you have a weird way of looking at things...  =)

Often times we already have one algorithm figured out in our heads...and this prevents us from seeing things from a different perspective.  That's one of the really nice things about EE...people read the problem and see completely different things...and then often bring different approaches to the table.

...don't start the "line counting" games though...we'll have to lump you in with the C/C++ programmers mentality of "less must be better!".   =\

Here is my algorithm with even fewer lines:
(it's super hard to read...but it ~must~ be better since it's shorter!)
``````    Private Function GetNextInterval() As Long
Dim dtTarget As New DateTime(DateTime.Now.AddDays(DayBox.SelectedIndex - DateTime.Now.DayOfWeek).Year, DateTime.Now.AddDays(DayBox.SelectedIndex - DateTime.Now.DayOfWeek).Month, DateTime.Now.AddDays(DayBox.SelectedIndex - DateTime.Now.DayOfWeek).Day, CInt(Split(TimeBox.Text, ":")(0)), CInt(Split(TimeBox.Text, ":")(1)), 0)
Return IIf(dtTarget < DateTime.Now, dtTarget.AddDays(7).Subtract(DateTime.Now).TotalMilliseconds, dtTarget.Subtract(DateTime.Now).TotalMilliseconds)
End Function
``````
0

LVL 85

Assisted Solution

Mike Tomlinson earned 425 total points
ID: 21796996
For grits and shins...and the betterment of the world (NOT!)...   ;)

The long sought after "one liner" function:
``````    Private Function GetNextInterval() As Long
End Function
``````
0

LVL 1

Author Comment

ID: 21797080
Yea, that's exactly why i post here too.

It's not that hard to read though, and it definitely IS better!!!!

/ducks for cover

=)

Thanks again!

J
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

### Suggested Solutions

Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
I think the Typed DataTable and Typed DataSet are very good options when working with data, but I don't like auto-generated code. First, I create an Abstract Class for my DataTables Common Code.  This class Inherits from DataTable. Also, it can …
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…