Reputation: 473763
I have a list of datetime.dates
and I need to check if each date is from the next consecutive month.
Hope it's clear what do I mean from the code:
import datetime
from unittest import TestCase
def is_consecutive(dates):
# TODO
return
class DatesTestCase(TestCase):
def test_consecutive(self):
self.assertTrue(is_consecutive([datetime.date(2010, 10, 3),
datetime.date(2010, 11, 8),
datetime.date(2010, 12, 1),
datetime.date(2011, 01, 11)]))
def test_not_consecutive(self):
self.assertFalse(is_consecutive([datetime.date(2010, 7, 6),
datetime.date(2010, 8, 24),
datetime.date(2010, 3, 5),
datetime.date(2010, 10, 25)]))
self.assertFalse(is_consecutive([datetime.date(2010, 10, 6),
datetime.date(2010, 11, 2),
datetime.date(2010, 12, 9),
datetime.date(2010, 01, 20)]))
How would you implement is_consecutive
?
Many thanks for any help (advise, hint, code or anything helpful)!
Upvotes: 1
Views: 2968
Reputation: 1087
Here's another solution to this problem:
def is_consecutive(dates):
months = [date.month for date in sorted(dates)] # extracting months from date, dates list has to be sorted first
months_diff = [abs(x - months[i - 1]) for i, x in enumerate(months) if i>0] # creates a resulting list of values after subtracting month with a previous month (absolute value is needed to account for the case when subtracting December(12) from January(1)
if not(set(months_diff) - set([1,11])): # if months_diff contains any values other than 11 and 1 then dates are not consecutive
return True
return False
Upvotes: 1
Reputation: 103714
This works on your examples and should work generally:
def is_consecutive(data):
dates=data[:]
while len(dates)>1:
d2=dates.pop().replace(day=1)
d1=dates[-1].replace(day=1)
d3=d1+datetime.timedelta(days=32)
if d3.month!=d2.month or d3.year!=d2.year:
return False
return True
Upvotes: 2
Reputation: 25908
Loop through each item of the list except the last, and compare it to the next item. Two items are consecutive if the month of the second is exactly one greater than the month of the first, or if the month of the second is 1 and the year of the second is exactly one greater than the year of the first. Return False
at the first failure, otherwise return True
at the end.
EDIT: In the second case, obviously the month of the first must be 12, in addition to the month of the second being 1. Code updated.
EDIT 2: And in the first case, obviously the year should be the same. That's what you get for writing too quickly.
F'rinstance:
#!/usr/bin/python
from datetime import date
def is_consecutive(datelist):
for idx, my_date in enumerate(datelist[:-1]):
if ((datelist[idx + 1].month - my_date.month == 1 and
datelist[idx + 1].year == my_date.year) or
(datelist[idx + 1].month == 1 and
my_date.month == 12 and
datelist[idx + 1].year - my_date.year == 1)):
continue
else:
return False
return True
print is_consecutive([date(2010, 10, 3),
date(2010, 11, 8),
date(2010, 12, 1),
date(2011, 1, 11)])
print is_consecutive([date(2010, 7, 6),
date(2010, 8, 24),
date(2010, 3, 5),
date(2010, 10, 25)])
An alternative implementation, possibly easier to follow but basically doing the same thing:
def is_consecutive(datelist):
for idx, my_date in enumerate(datelist[:-1]):
month_diff = datelist[idx + 1].month - my_date.month
year_diff = datelist[idx + 1].year - my_date.year
if ((month_diff == 1 and year_diff == 0) or
(month_diff == -11 and year_diff == 1)):
continue
else:
return False
return True
Upvotes: 2