# Consecutive days - Best way

• ### Question

• Hi,

I have a collection of dates, these dates are not in any order.. I need to find if this collection has any consecutive dates..

The collection has only days from Mon - Fri....

If a friday and a monday are on the collection ie  6/4/2012 and 9/4/2012.. that is considered to be consecutive

so is the best way to compare each date with the collection and check to see if the datediff is 1? and have a condition to check for mondays and fridays? (ie date diff 4)

Thanks

Vik

System developer & support analyst

Thursday, April 5, 2012 3:17 AM

• Just trying to clear it up - maybe the message in the other branch got lost - the OP wrote

"I looped through the collection of dates checking each date to each other.. checking if if the date diff is 1.. (consevutive day) or if the date diff is 3 and checking the weekdays of the two days (in case of friday and monday)"

I think this is the same approach as RiceD's. However, that's not a problem because, as I also think like Cor, there's not a much more elegant solution than this.

Armin

Thursday, April 5, 2012 4:27 PM
• I'd suggest sorting the dates in order (perhaps in a copy). Then loop through with something like this pseudo-code:

for d = 0 to NumberOfDates-1
if date(d) is Friday and date(d+1) is Monday and difference(date(d), date(d+1) = 3 then
Do True stuff
else
if  difference(date(d), date(d+1) = 1 then
Do True stuff
else
Do False stuff
end if
end if

A bit of thought might simplify the ifs but they describe the conditions.

Regards David R
---------------------------------------------------------------
The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
Every program eventually becomes rococo, and then rubble. - Alan Perlis
The only valid measurement of code quality: WTFs/minute.

• Proposed as answer by Thursday, April 5, 2012 10:38 AM
• Marked as answer by Saturday, April 21, 2012 6:43 AM
Thursday, April 5, 2012 10:29 AM

### All replies

• Vik,

It sounds like what you're really trying to do is to come up with "is it a weekday?". If so, then you can use this:

http://msdn.microsoft.com/en-us/library/82yfs2zh(v=VS.80).aspx

If not then maybe explain a bit more about what you're trying to get.

Thursday, April 5, 2012 3:31 AM
• The question here is what are you trying to do with checking these consecutive dates? Return a true or false value? Get a list or a collection/array of these consecutive "dates"? etc...

If a post helps you in any way or solves your particular issue, please remember to use the Propose As Answer option or Vote As Helpful
Visit the Forum: TechLifeForum

Thursday, April 5, 2012 4:07 AM
• yes just return a true or false date..

basically here is a list of dates.. tell me if there are any consecutive dates in the list of dates.. true or false..

I have implemented this.. just wanted to know if there is a better way?

The way I implemented is..

I looped through the collection of dates checking each date to each other.. checking if if the date diff is 1.. (consevutive day) or if the date diff is 3 and checking the weekdays of the two days (in case of friday and monday)

System developer & support analyst

Thursday, April 5, 2012 4:54 AM
• yes just return a true or false date..

basically here is a list of dates.. tell me if there are any consecutive dates in the list of dates.. true or false..

I have implemented this.. just wanted to know if there is a better way?

The way I implemented is..

I looped through the collection of dates checking each date to each other.. checking if if the date diff is 1.. (consevutive day) or if the date diff is 3 and checking the weekdays of the two days (in case of friday and monday)

System developer & support analyst

Vik,

AFAIK there is no other way and then probably also not a "better" way. Be aware that short written code using expressions does not always end with a faster program. (Of course real steps can make a difference but I would not know how that would be done in your case. There is no function which returns simply what you want to get). I don't know if you used DateDiff or TimeSpan and that is also only optical and does not change much in the performance.

Success
Cor

• Edited by Thursday, April 5, 2012 7:51 AM wordiness
Thursday, April 5, 2012 5:26 AM
• I'd suggest sorting the dates in order (perhaps in a copy). Then loop through with something like this pseudo-code:

for d = 0 to NumberOfDates-1
if date(d) is Friday and date(d+1) is Monday and difference(date(d), date(d+1) = 3 then
Do True stuff
else
if  difference(date(d), date(d+1) = 1 then
Do True stuff
else
Do False stuff
end if
end if

A bit of thought might simplify the ifs but they describe the conditions.

Regards David R
---------------------------------------------------------------
The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
Every program eventually becomes rococo, and then rubble. - Alan Perlis
The only valid measurement of code quality: WTFs/minute.

• Proposed as answer by Thursday, April 5, 2012 10:38 AM
• Marked as answer by Saturday, April 21, 2012 6:43 AM
Thursday, April 5, 2012 10:29 AM
• Riced,

That is in my perception the solution the OP has done, he ask for better ways.

:-)

Success
Cor

Thursday, April 5, 2012 11:04 AM
• Cor

Not so - OP says they are not in any order. And that makes a difference as to how you can do the comparisons.

By sorting you get it down to order N, otherwise it's N^2. I think that's about right - sorting means you can use one loop; unsorted means using loop within loop. Of course I might have misunderstood the OP's situation.

Regards David R
---------------------------------------------------------------
The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
Every program eventually becomes rococo, and then rubble. - Alan Perlis
The only valid measurement of code quality: WTFs/minute.

Thursday, April 5, 2012 11:20 AM
• Cor

Not so - OP says they are not in any order. And that makes a difference as to how you can do the comparisons.

David,

He does not say that, he says they do not start in any order, and then he gives a solution which is the same likewise yours.

Be aware, I was starting like you before I became aware of the real question of the OP. Therefore I recognized you did the same.

Success
Cor

Thursday, April 5, 2012 2:43 PM
• Cor

Not so - OP says they are not in any order. And that makes a difference as to how you can do the comparisons.

David,

He does not say that, he says they do not start in any order, and then he gives a solution which is the same likewise yours.

Be aware, I was starting like you before I became aware of the real question of the OP. Therefore I recognized you did the same.

Success
Cor

Based on precisely what the OP stated - the dates are not in any order. 'Starting' is irrelevant. The OPs solution also indicates that the dates are not likely to be sorted.

Additionally, Riced's solution is different from the OPs solution: the OP appears to have (as already mentioned) a Loop-within-a-loop, while Riced (David R.) offers a valid alternative, a Sort-then-a-loop. Davids solution is NOT the same as the OPs solution.

As far which is 'best' depends on what 'best' means. Both are valid. Even considering that a sort is a 'loop within a loop' itself, the sort-then-loop would be marginally faster depending on the sort algorithm. If a sorted collection could be used (potentially) elsewhere for other calculations, then sorting first would be a no-brainer. Either way, it cannot be done without loops, and I cannot think of a more straightforward way other than the OPs solution or Davids solution (which has been marked as a potential answer).

Stephen J Whiteley

Thursday, April 5, 2012 4:17 PM
• Just trying to clear it up - maybe the message in the other branch got lost - the OP wrote

"I looped through the collection of dates checking each date to each other.. checking if if the date diff is 1.. (consevutive day) or if the date diff is 3 and checking the weekdays of the two days (in case of friday and monday)"

I think this is the same approach as RiceD's. However, that's not a problem because, as I also think like Cor, there's not a much more elegant solution than this.

Armin

Thursday, April 5, 2012 4:27 PM
• Maybe I'm making much ado of nothing (it wouldn't be the first time), but it seems to me that a DateDiff value of 4 is Monday and Friday of the same week because the DayOfWeek enumerator is reset to 0 on the first day of the week.

The following may be totally not needed, but for what it's worth:

```    Public Class ConsecutiveDate
Public Date1 As DateTime
Public Date2 As DateTime
End Class
'
Private rand As New Random
'
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Dim dList As New List(Of DateTime)
Dim resultList As New List(Of ConsecutiveDate)
'
For i As Integer = 1 To 2000
Dim offset As Integer = rand.Next(1, 2000)
Dim d As DateTime = Today.AddDays(offset)
If Not dList.Contains(d) Then
End If
Next
'
Dim allDaysTextFile As String = _
My.Computer.FileSystem.SpecialDirectories.Desktop & "\AllDays.txt"
Dim sb As New System.Text.StringBuilder
'
For i As Integer = 0 To dList.Count - 1
sb.AppendLine(dList(i).ToLongDateString)
Next
'
My.Computer.FileSystem.WriteAllText(allDaysTextFile, sb.ToString, False)
'
dList.Sort()
'
For i As Integer = 0 To dList.Count - 1
If i > 0 Then
Dim dayBefore As DateTime = dList(i - 1)
Dim thisDay As DateTime = dList(i)
Dim containsFriday As Boolean = False
If dayBefore.DayOfWeek = DayOfWeek.Friday OrElse _
thisDay.DayOfWeek = DayOfWeek.Friday Then
containsFriday = True
End If
'
If dayBefore.DayOfWeek > DayOfWeek.Sunday AndAlso _
dayBefore.DayOfWeek < DayOfWeek.Saturday Then
'
If thisDay.DayOfWeek > DayOfWeek.Sunday AndAlso _
thisDay.DayOfWeek < DayOfWeek.Saturday Then
'
If containsFriday Then
' Determine which of them is Friday
If dayBefore.DayOfWeek = DayOfWeek.Friday Then
If thisDay.DayOfWeek = DayOfWeek.Monday Then
Dim thisDateSet As New ConsecutiveDate
With thisDateSet
.Date1 = dayBefore
.Date2 = thisDay
End With
End If
Else
If dayBefore.DayOfWeek = DayOfWeek.Monday Then
If DateDiff(DateInterval.Day, dayBefore, thisDay) = 4 Then
Dim thisDateSet As New ConsecutiveDate
With thisDateSet
.Date1 = dayBefore
.Date2 = thisDay
End With
End If
End If
End If
Else
If DateDiff(DateInterval.Day, dayBefore, thisDay) = 1 Then
Dim thisDateSet As New ConsecutiveDate
With thisDateSet
.Date1 = dayBefore
.Date2 = thisDay
End With
End If
End If
End If
End If
End If
Next
'
Dim consecutiveDaysFile As String = _
My.Computer.FileSystem.SpecialDirectories.Desktop & "\ConsecutiveDays.txt"
sb.Length = 0
'
For i As Integer = 0 To resultList.Count - 1
If i > 0 Then
sb.AppendLine()
sb.AppendLine("------------------------------")
sb.AppendLine()
End If
sb.AppendLine(resultList(i).Date1.ToLongDateString)
sb.AppendLine(resultList(i).Date2.ToLongDateString)
Next
'
My.Computer.FileSystem.WriteAllText(consecutiveDaysFile, sb.ToString, False)
Stop
End Sub```

This is the random list of dates that it generated:

Click To Open

and this is the "sets" of consecutive days that it generated:

Click To Open

...for what it's worth

Thursday, April 5, 2012 4:48 PM
• I screwed that up - I just went and added the datediff=4 anyway and my intent was to generate ANOTHER list to show what I meant of those which are Monday and Friday of the same week.

Hopefully it makes sense but as it is, you'll need to remove that entire "else" segment".

Thursday, April 5, 2012 4:53 PM
• Yes - here's the list of those it found that have a datediff=4:

http://www.fls-tech.com/VBNet_Forum/04-05-12/DateDiff_4.txt

Thursday, April 5, 2012 5:06 PM
• Maybe I'm overlooking something, but this should do it:

```   Shared Function HasConsecutiveDays(ByVal Values As IEnumerable(Of DateTime)) As Boolean

Dim Indexes = (From d In Values Order By d _
Select DayIndex = (d.Date - DateTime.MinValue).Days _
Select Dayindex = (DayIndex \ 7) * 5 + (DayIndex Mod 7)).ToArray

Return Aggregate i In Indexes.Skip(1).Where(Function(i, LoopIndex) Indexes(LoopIndex) = i - 1) Into Any()

End Function```

EDIT: The function is map is each day to a day number, then scales it to 5 days a week. The final value is comparable without a week end gap.

Armin

Thursday, April 5, 2012 5:21 PM
• Maybe I'm overlooking something, but this should do it:

```   Shared Function HasConsecutiveDays(ByVal Values As IEnumerable(Of DateTime)) As Boolean

Dim Indexes = (From d In Values Order By d _
Select DayIndex = (d.Date - DateTime.MinValue).Days _
Select Dayindex = (DayIndex \ 7) * 5 + (DayIndex Mod 7)).ToArray

Return Aggregate i In Indexes.Skip(1).Where(Function(i, LoopIndex) Indexes(LoopIndex) = i - 1) Into Any()

End Function```

Armin

Wow - you're much better in LINQ than I am (well heck, you're much better with all of it than me), so if you say that it works I'll take your word on it!

Do you see my point though about a DateDiff=4 as being the Monday and Friday of the same week?

Thursday, April 5, 2012 5:27 PM
• Cor

Compare these the first is the OP's solution as I see it, the second is what I suggested might be a way to do it. I'd say they are not the same.

The Op's method as inferred from description
' declare variables i, j, found
' init i = 0, found = false
j = 0
found = DaysAreConsecutive(dates(i), dates(j))
end while
end while
(Depending on how DaysAreConsecutive is implemented the inner loop could go from j=i+1.)

Another method - may be better depends on what is meant and the data
' declare variables i, found
' init i = 0, found = false
SortDates()
found = DaysAreConsecutive(dates(i), dates(i+1))
end while
Based on the actual wording in the original post there is no basis to assume any ordering has been done by the OP.

I can't claim my method is better. It might be, but depends on such things as volume of data. If there are only a few it will make little difference. On the other hand it could make quite a difference. I once changed an implementation from the (inferred) OP's method to my method, run time reduced from over 50mins to under 2mins.

Regards David R
---------------------------------------------------------------
The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
Every program eventually becomes rococo, and then rubble. - Alan Perlis
The only valid measurement of code quality: WTFs/minute.

Thursday, April 5, 2012 6:11 PM
• I'm not completely sure if it works. :) Someone'd better ran some tests. LINQ's hard to debug.

I don't use the DateDiff function, but, yes, it's 4 days.

Armin

Thursday, April 5, 2012 6:26 PM
• I don't use the DateDiff function, but, yes, it's 4 days.

Armin

It's a nice function because it takes in such things as leap year and it's pretty fast.

But given these three conditions:

- The two days are weekdays (ergo, not Saturday nor Sunday)
- One of the days is Friday
- The days between is four

It HAS to be Monday and Friday of the same week. If it's looking at Monday of the following week the difference will be negative because on Sunday, the enumerator is reset back to zero.

Thursday, April 5, 2012 6:29 PM
• Frank, Armin

I think the OP made a typo in first post (i.e. 4) because in second post used 3 (which is correct for Friday to Monday).

I think it's not only hard to debug (I'll take your word for that) but borders on incomprehensibility. But that's just an old man's take on LINQ in general. :)

Regards David R
---------------------------------------------------------------
The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
Every program eventually becomes rococo, and then rubble. - Alan Perlis
The only valid measurement of code quality: WTFs/minute.

Thursday, April 5, 2012 6:33 PM
• Frank, Armin

I think the OP made a typo in first post (i.e. 4) because in second post used 3 (which is correct for Friday to Monday).

I think it's not only hard to debug (I'll take your word for that) but borders on incomprehensibility. But that's just an old man's take on LINQ in general. :)

Regards David R
---------------------------------------------------------------
The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
Every program eventually becomes rococo, and then rubble. - Alan Perlis
The only valid measurement of code quality: WTFs/minute.

Ah ok - and depending on which direction you use for Date1 and Date2, yes that's possible.

As for LINQ, it's really quite powerful but you're right, debugging it when it doesn't work is a pain. About the only way that I ever have been able to is to "build it up" little at a time and keep testing it over and over.

But if it later just doesn't work for some weird reason or another ... you're back to tearing it apart again and testing.

In something that I wrote the other day (for a forum member) I tried something I'd been thinking of for a while. Let's say that you have a database of names. Four names which really ARE the same thing ... but hard to evaluate might be:

- "Frank Smith"
- "frank smith"
- "FrankSmith"
- "Frank      Smith"

I used LINQ to resolve it and it's not that tough at all. This is totally off-topic for this thread but let me know if you'd like me to post the solution. It's actually just a few lines of code using LINQ.

Thursday, April 5, 2012 6:40 PM
• But given these three conditions:

- The two days are weekdays (ergo, not Saturday nor Sunday)
- One of the days is Friday
- The days between is four

It HAS to be Monday and Friday of the same week. If it's looking at Monday of the following week the difference will be negative because on Sunday, the enumerator is reset back to zero.

I'm not quite sure what's the point. That's only of you don't consider the week. If you're referring to my code (are you?), I'm multiplying the week by 5 before adding the day offset (0..4), so the next monday is always greater than the friday before.

Armin

Thursday, April 5, 2012 6:45 PM
• I'm not quite sure what's the point. That's only of you don't consider the week. If you're referring to my code (are you?), I'm multiplying the week by 5 before adding the day offset (0..4), so the next monday is always greater than the friday before.

Armin

No, I was referring to the OP's logic (although David said that he later said three days), but originally he said "... and have a condition to check for mondays and fridays? (ie date diff 4)..."

If one day is a Friday and the DateDiff=4 then the other date has to be Monday of that same week (unless he's taking absolute value - or interchanging D1 for D2 - in which case it could also be Tuesday of the following week).

But either way, they aren't "consecutive days" in the sense that's he's asking about...

Thursday, April 5, 2012 6:50 PM
• No, I was referring to the OP's logic (although David said that he later said three days), but originally he said "... and have a condition to check for mondays and fridays? (ie date diff 4)..."

If one day is a Friday and the DateDiff=4 then the other date has to be Monday of that same week (unless he's taking absolute value - or interchanging D1 for D2 - in which case it could also be Tuesday of the following week).

Well, yes, no, ummm, yes,  LOL     It's 4 days in one direction and 3 in the other one. I think he means to exclude (not include) a difference of 4 days to be recognized it as two consecutive days. Depends on the point of view.

Armin

Thursday, April 5, 2012 7:10 PM
• No, I was referring to the OP's logic (although David said that he later said three days), but originally he said "... and have a condition to check for mondays and fridays? (ie date diff 4)..."

If one day is a Friday and the DateDiff=4 then the other date has to be Monday of that same week (unless he's taking absolute value - or interchanging D1 for D2 - in which case it could also be Tuesday of the following week).

Well, yes, no, ummm, yes,  LOL     It's 4 days in one direction and 3 in the other one. I think he means to exclude (not include) a difference of 4 days to be recognized it as two consecutive days. Depends on the point of view.

Armin

I agree - what he's asked for leaves a lot to be desired.

For instance, is he passing in a list (he never said what sort of collection it was) of all dates or just evaluating each two dates at a time? Does he want a boolean indicating that they're "consecutive" in the sense that he means or does he want a list of all consecutive ones back, given a starting date and ending date or ...?

It's wide open right now.

I look forward to seeing if he'll expound on what he's passing in and what he wants back.

Thursday, April 5, 2012 7:15 PM
• I would say quite simply, as the OP has quite simply stated, a Friday followed by (the following) Monday is a consecutive day. Regardless of how you determine it, this should return true for the function.

```Public Class Form1

' Should be consecutive (spans a weekend)
Dim d() As DateTime = New DateTime() {#4/4/2012#, #4/6/2012#, #4/9/2012#, #4/11/2012#, #4/13/2012#, #4/17/2012#, #4/19/2012#}
Dim result As Boolean = Consecutive(d)
Debug.WriteLine(result)
' Should be consecutive (two weekdays)
d = New DateTime() {#4/4/2012#, #4/6/2012#, #4/10/2012#, #4/11/2012#, #4/13/2012#, #4/17/2012#, #4/19/2012#}
result = Consecutive(d)
Debug.WriteLine(result)
' Should NOT be consecutive
d = New DateTime() {#4/4/2012#, #4/6/2012#, #4/10/2012#, #4/12/2012#, #4/14/2012#, #4/16/2012#, #4/18/2012#}
result = Consecutive(d)
Debug.WriteLine(result)
End Sub

Public Function Consecutive(dates() As DateTime) As Boolean
Call Array.Sort(dates)
Dim prev As DateTime
For Each d As DateTime In dates
' Ignore saturday and sundays
If d.DayOfWeek = DayOfWeek.Saturday OrElse d.DayOfWeek = DayOfWeek.Sunday Then Continue For
' get just the date
Dim dt As DateTime = d.Date
Dim dayDifference As Integer = dt.Subtract(prev).Days
If dayDifference = 1 Then Return True
If dt.DayOfWeek = DayOfWeek.Monday AndAlso dayDifference = 3 Then Return True
' Set the previous date
prev = dt
Next
Return False
End Function
End Class```
I'm not a fan of LINQ (it's kind of an electric hammer 'as seen on TV') so the above is an alternative, pretty much replicating what David R was demonstrating with the pseudo-code.

Stephen J Whiteley

Thursday, April 5, 2012 8:10 PM