alecxe
alecxe

Reputation: 473763

Determine consecutive dates

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

Answers (3)

barmaley
barmaley

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

dawg
dawg

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

Crowman
Crowman

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

Related Questions