Как определить, являются ли даты последовательными в Python? - PullRequest
6 голосов
/ 06 марта 2012

У меня есть таблица доступа с полем «Дата».у него есть случайные даты для каждой записи.Я построил сценарий для добавления всех записей в список, а затем настроить список для фильтрации только уникальных значений:

dateList = []
# cursor search through each record and append all records in the date 
# field to a python list
for row in rows:
   dateList.append(row.getValue("DATE_OBSERVATION").strftime('%m-%d-%Y'))

# Filter unique values to a set
newList = list(set(dateList))

Это возвращает (в моей тестовой таблице):

['07-06-2010', '06 -24-2010 ', '07 -05-2010', '06 -25-2010 '] *

Теперь у меня есть уникальные значения для "DATE_OBSERVATION ", я хочу определить, если:

  • даты одиночные (т. Е. Возвращается только одна уникальная дата, потому что это дата в каждой записи)
  • , если датыдиапазон дат (т.е. все даты попадают в последовательный диапазон)
  • , если даты являются несколькими датами, но не находятся в диапазоне последовательных дат

Любые предложения будутбыть высоко ценится!Mike

Ответы [ 4 ]

12 голосов
/ 06 марта 2012

Вместо того, чтобы использовать собственную функцию consecutive, вы можете просто преобразовать объекты даты в целые числа, используя метод .toordinal() объектов datetime. Разница между максимальным и минимальным значением набора порядковых дат на единицу больше длины набора:

from datetime import datetime

date_strs = ['07-06-2010', '06-24-2010', '07-05-2010', '06-25-2010']
# date_strs = ['02-29-2012', '02-28-2012', '03-01-2012']
# date_strs = ['01-01-2000']
dates = [datetime.strptime(d, "%m-%d-%Y") for d in date_strs]

date_ints = set([d.toordinal() for d in dates])

if len(date_ints) == 1:
    print "unique"
elif max(date_ints) - min(date_ints) == len(date_ints) - 1:
    print "consecutive"
else:
    print "not consecutive"
1 голос
/ 22 февраля 2014

Другая версия, использующая ту же логику, что и в моем другом ответе.

from datetime import date, timedelta

# Definition 1: 1/1/14, 1/2/14, 1/2/14, 1/3/14 is consider consecutive
# Definition 2: 1/1/14, 1/2/14, 1/2/14, 1/3/14 is consider not consecutive

# datelist = [date(2014, 1, 1), date(2014, 1, 3),
#             date(2013, 12, 31), date(2013, 12, 30)]

# datelist = [date(2014, 2, 19), date(2014, 2, 19), date(2014, 2, 20),
#             date(2014, 2, 21), date(2014, 2, 22)]

datelist = [date(2014, 2, 19), date(2014, 2, 21),
            date(2014, 2, 22), date(2014, 2, 20)]

datelist.sort()

previousdate = datelist[0]

for i in range(1, len(datelist)):
    #if (datelist[i] - previousdate).days == 1 or (datelist[i] - previousdate).days == 0:  # for Definition 1
    if (datelist[i] - previousdate).days == 1:    # for Definition 2
        previousdate = datelist[i]
    else:
        previousdate = previousdate + timedelta(days=-1)

if datelist[-1] == previousdate:
    print "dates are consecutive"
else:
    print "dates are not consecutive"
0 голосов
/ 22 февраля 2014

Вот моя версия с использованием функции redu ().

from datetime import date, timedelta


def checked(d1, d2):
    """
    We assume the date list is sorted.
    If d2 & d1 are different by 1, everything up to d2 is consecutive, so d2
    can advance to the next reduction.
    If d2 & d1 are not different by 1, returning d1 - 1 for the next reduction
    will guarantee the result produced by reduce() to be something other than
    the last date in the sorted date list.

    Definition 1: 1/1/14, 1/2/14, 1/2/14, 1/3/14 is consider consecutive
    Definition 2: 1/1/14, 1/2/14, 1/2/14, 1/3/14 is consider not consecutive

    """
    #if (d2 - d1).days == 1 or (d2 - d1).days == 0:  # for Definition 1
    if (d2 - d1).days == 1:                          # for Definition 2
        return d2
    else:
        return d1 + timedelta(days=-1)

# datelist = [date(2014, 1, 1), date(2014, 1, 3),
#             date(2013, 12, 31), date(2013, 12, 30)]

# datelist = [date(2014, 2, 19), date(2014, 2, 19), date(2014, 2, 20),
#             date(2014, 2, 21), date(2014, 2, 22)]

datelist = [date(2014, 2, 19), date(2014, 2, 21),
            date(2014, 2, 22), date(2014, 2, 20)]

datelist.sort()

if datelist[-1] == reduce(checked, datelist):
    print "dates are consecutive"
else:
    print "dates are not consecutive"
0 голосов
/ 06 марта 2012

Используйте вашу базу данных для выбора уникальных дат в порядке возрастания:

  • если запрос возвращает одну дату, это ваш первый случай

  • В противном случае выясните, являются ли даты последовательными:

    import datetime
    
    def consecutive(a, b, step=datetime.timedelta(days=1)):
        return (a + step) == b
    

Расположение кода:

dates = <query database>
if all(consecutive(dates[i], dates[i+1]) for i in xrange(len(dates) - 1)):
   if len(dates) == 1: # unique
      # 1st case: all records have the same date
   else:
      # the dates are a range of dates
else:
   # non-consecutive dates
...