Timespan perplexing, please help with brain freeze.

  • Thread starter Thread starter sd00
  • Start date Start date
S

sd00

Hi all, can someone give me some coding help with a problem that
*should* be really simple, yet I'm struggling with.

I need the difference between 2 times (Target / Actual)
However, these times will fall somewhere between a Start & End time
Further more, there will be Break & Lunch times between Start & End.

Example...
Start 08:00
Break start 10:30
Break end 10:40
Lunch start 12:00
Lunch end 12:30
Break start 14:30
Break end 14:40
End 16:00

Target 10:12
Actual 10:36

Target vs. Actual (results)....
Real Time - 24 min
Production Time - 18 min


NOTES:
The solution will cater for any amount of delay e.g.
Target "1-Feb-06 14:23", Actual "2-Feb-06 11:52")

How I imagined I'd do this...

Dim ts as TimeSpanEx
ts.AddStart "1-Feb-06 08:00"
ts.AddStop "1-Feb-06 10:30"
ts.AddStart "1-Feb-06 10:40"
ts.AddStop "1-Feb-06 12:00"
ts.AddStart "1-Feb-06 12:30"
ts.AddStop "1-Feb-06 14:30"
ts.AddStart "1-Feb-06 14:40"
ts.AddStop "1-Feb-06 16:00"

ts.AddStart "2-Feb-06 08:00"
ts.AddStop "2-Feb-06 10:30"
ts.AddStart "2-Feb-06 10:40"
ts.AddStop "2-Feb-06 12:00"
ts.AddStart "2-Feb-06 12:30"
ts.AddStop "2-Feb-06 14:30"
ts.AddStart "2-Feb-06 14:40"
ts.AddStop "2-Feb-06 16:00"

Dim tsResult as TimeSpan
tsResult = ts.CalculateDuration("1-Feb-06 14:23", "2-Feb-06 11:52" )

....Just gotta figure out the contents of TimeSpanEx class!

I can create the AddStart & AddStop functions (store times in an array or list) but I
cannot for the life of me get a working CalculateDuration(Target, Actual) function going.


I hope the answer is so obvious & simple that I kick myself for days!

Thanks, Steve.
 
Hi Steve,

I'm sure someone will be able to help you with this... but couldn't
resist saying this :
//
Start 08:00
Break start 10:30
Break end 10:40
Lunch start 12:00
Lunch end 12:30
Break start 14:30
Break end 14:40
End 16:00
\\

Man ! Wish I had those kind of breaks ! ;-))

Regards,

Cerebrus.
 
Hi SD00,

I don't know if this is a student question. It looks like that.

We try not to help with those.

It looks like that because I see no eliminiations.

Your problem is what affects your caculation and that is only the start of
the break starts at 10:30 while the end of that is later than the end of the
Actual. So the begin time of that replaces the end time of the time you have
to calculate. In fact is that all.

I hope this helps,

Cor
 
You obviously have a class (TimeSpanEx) that implements this
CalculateDuration method.

Because we have no way of knowing what actually happens in this class, it is
difficult for us to advise you on how to make it work correctly.

That said, if I were to attempt to implement a similar type of functionality
then this is the way I would approach it.

- Treat each 'work period' as a TimeCard object that has both a
StartTime and an EndTime property (DateTime)

- The TimeCard object would be considered to be complete if both
The StartTime and EndTime properties have a valid value.

- The TimeCard object would possibly have a readonly Duration
property (TimeSpan) that returns the difference between the
StartTime and EndTime properties or Nothing if the TimeCard
object is incomplete.

- A TimeCards object would be implemented as a collection of
TimeCard objects with a Duration method (TimeSpan)
that would return the total of the timespans of the individual
TimeCard objects that are complete. Overloads of the Duration
methods would possibly be implemented so that the result can
be filtered by datetime range(s) and other criteria.

- As long as start and end times are recorded in sequence then
there would be no problem assigning an end time to the
pertinent incomplete object.
 
This is not a student / college question!

Would it help if I said it was for a work project I'm lagging behind on! (truth)

Usually, I'll get the answer (be it elegant or brute force) but I have been struggling with this!

If you can help, please do!
 
Thanks for taking the time to try and help me.

I have considered lots of ways I can do this.

I have considered putting all the times into sorted arrays, running through them till I find Target > RunTimes(x) then
find Actual < StopTimes(x) then try to count up the production time in-between

I always get in knots & find a problem that means I have to start again.

I really am struggling with this one. If you can offer some coding as a solution / partial solution I'd be most
grateful.

I'm beginning to thing this one is tougher than first thought!
 
I'm sure someone will be able to help you with this... but couldn't
resist saying this :

Can that someone be you?

Regardless of the times specified here, this is an actual problem I have to get sorted. It is not a college project (as
someone here has already hinted at) it is for my work that is already behind schedule.

I am beginning to think this is a tough question for a newsgroup!

Perhaps I should try it on that site where programmers help you & win points (I forget the name!)

I would be grateful if someone could help coding this.

Cheers.
 
Try the following code. It is quick and dirty so dissect it, understand what
it is doing and adapt it to suit your needs. It should point you in the
right direction:

Public Class Form1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click

Dim _timecards As New TimeCards

_timecards.Add(New TimeCard(New DateTime(2006, 2, 1, 8, 0, 0), New
DateTime(2006, 2, 1, 10, 30, 0, 0)))

_timecards.Add(New TimeCard(New DateTime(2006, 2, 1, 10, 40, 0), New
DateTime(2006, 2, 1, 12, 0, 0, 0)))

_timecards.Add(New TimeCard(New DateTime(2006, 2, 1, 12, 30, 0), New
DateTime(2006, 2, 1, 14, 30, 0, 0)))

_timecards.Add(New TimeCard(New DateTime(2006, 2, 1, 14, 40, 0), New
DateTime(2006, 2, 1, 16, 0, 0, 0)))

_timecards.Add(New TimeCard(New DateTime(2006, 2, 2, 8, 0, 0), New
DateTime(2006, 2, 2, 10, 30, 0, 0)))

_timecards.Add(New TimeCard(New DateTime(2006, 2, 2, 10, 40, 0), New
DateTime(2006, 2, 2, 12, 0, 0, 0)))

_timecards.Add(New TimeCard(New DateTime(2006, 2, 2, 12, 30, 0), New
DateTime(2006, 2, 2, 14, 30, 0, 0)))

_timecards.Add(New TimeCard(New DateTime(2006, 2, 2, 14, 40, 0), New
DateTime(2006, 2, 2, 16, 0, 0, 0)))

Console.WriteLine("_timecards.Duration = {0}", _timecards.Duration)

Console.WriteLine("_timecards.Duration(New DateTime(2006, 2, 1)) =
{0}", _timecards.Duration(New DateTime(2006, 2, 1)))

Console.WriteLine("_timecards.Duration(New DateTime(2006, 2, 2)) =
{0}", _timecards.Duration(New DateTime(2006, 2, 2)))

Console.WriteLine("_timecards.Duration(New DateTime(2006, 2, 1, 14,
23, 0, 0), New DateTime(2006, 2, 2, 11,52,0,0)) = {0}",
_timecards.Duration(New DateTime(2006, 2, 1, 14, 23, 0, 0), New
DateTime(2006, 2, 2, 11, 52, 0, 0)))

End Sub

End Class

Public Class TimeCard

Private m_starttime As DateTime = DateTime.MinValue
Private m_endtime As DateTime = DateTime.MinValue

Public Sub New()

End Sub

Public Sub New(ByVal starttime As DateTime)

m_starttime = starttime

End Sub

Public Sub New(ByVal starttime As DateTime, ByVal endtime As DateTime)

m_starttime = starttime

m_endtime = endtime

End Sub

Public Property StartTime() As DateTime

Get
Return m_starttime
End Get

Set(ByVal value As DateTime)
m_starttime = value
End Set

End Property

Public Property EndTime() As DateTime

Get
Return m_endtime
End Get

Set(ByVal value As DateTime)
m_endtime = value
End Set

End Property

Public ReadOnly Property IsComplete() As Boolean

Get
Return (m_starttime > DateTime.MinValue AndAlso m_endtime >=
m_starttime)
End Get

End Property

Public ReadOnly Property Duration() As TimeSpan

Get
If Me.IsComplete Then
Return m_endtime.Subtract(m_starttime)
Else
Return TimeSpan.Zero
End If
End Get

End Property

End Class

Public Class TimeCards

Private m_timecards As New ArrayList

Public Sub New()

End Sub

Public ReadOnly Property Count() As Integer

Get
Return m_timecards.Count
End Get

End Property

Public Function Add(ByVal timecard As TimeCard) As Integer

Return m_timecards.Add(timecard)

End Function

Public ReadOnly Property Item(ByVal index As Integer) As TimeCard

Get
Return CType(m_timecards(index), TimeCard)
End Get

End Property

Public ReadOnly Property Item(ByVal starttime As DateTime) As TimeCard

Get
For Each _t As TimeCard In m_timecards
If _t.StartTime = starttime Then Return _t
Next
Return Nothing
End Get

End Property

Public ReadOnly Property Item(ByVal starttime As DateTime, ByVal
searchtype As SearchType) As TimeCard

Get
For Each _t As TimeCard In m_timecards
Select Case searchtype
Case searchtype.Equal
If _t.StartTime = starttime Then Return _t
Case searchtype.GreaterThanOrEqual
If _t.StartTime >= starttime Then Return _t
End Select
Next
Return Nothing
End Get

End Property

Public ReadOnly Property Duration() As TimeSpan

Get
Dim _result As TimeSpan = TimeSpan.Zero
For Each _t As TimeCard In m_timecards
_result = _result.Add(_t.Duration)
Next
Return _result
End Get

End Property

Public ReadOnly Property Duration(ByVal fordate As DateTime) As TimeSpan

Get
Dim _result As TimeSpan = TimeSpan.Zero
For Each _t As TimeCard In m_timecards
If _t.StartTime.Date = fordate.Date Then _result =
_result.Add(_t.Duration)
Next
Return _result
End Get

End Property

Public ReadOnly Property Duration(ByVal starttime As DateTime, ByVal
endtime As DateTime) As TimeSpan

Get
Dim _result As TimeSpan = TimeSpan.Zero
For Each _t As TimeCard In m_timecards
If _t.IsComplete AndAlso _t.EndTime >= starttime AndAlso
_t.StartTime <= endtime Then
If _t.StartTime >= starttime AndAlso _t.EndTime <= endtime Then
_result = _result.Add(_t.Duration)
Else
If _t.StartTime < starttime AndAlso _t.EndTime <= endtime Then
_result = _result.Add(_t.EndTime.Subtract(starttime))
Else
If _t.StartTime >= starttime AndAlso _t.EndTime > endtime
Then
_result = _result.Add(endtime.Subtract(_t.StartTime))
End If
End If
End If
End If
Next
Return _result
End Get

End Property

End Class

Public Enum SearchType
Equal = 0
GreaterThanOrEqual = 1
End Enum
 
SD,

Read my full message, i told how to do it, it seems pretty easy for me.

You told you had a brain freeze I told that you had to eleminiate some
things.

All things that fall outside the 10:12 - 10:36 area are not important
See than my answer, problem is maybe how you create that table, but you gave
it us in pseudo but in fact it is nothing more than a table.

Cor
 
I appreciate your help & I would do the same thing (help in a way that helps more - i.e. give clues) but really, I was
stumped.

Fortunately Stephany Young has helped me enormously.

Thanks for your input.
 
Almost perfect.

1 omission from the function...
Public ReadOnly Property Duration(ByVal starttime As DateTime, ByVal endtime As DateTime) As TimeSpan
.... where a start time ~ end time within a 'production time' was not accounted for.

Thanks you very much.
 
As I said, it was quick and dirty and offerred to point in the right
direction.

That said, you should not consider it to be the only way to go about it.
There will be as many different solutions ans there are competent
programmers.
 
Indeed, I consider myself (well I used to!) competent programmer but for some reason, I could see no solution! I almost
hard coded the solution (if this then else if this then blah blah)

I have no doubt there will be more elegant & clever ways, but still I am grateful as now I have a working solution.

Gracias amiga.
 
Back
Top