¿Cómo detectar si las fechas son consecutivas en Python?

Tengo una tabla de acceso con un campo ‘Fecha’. Tiene fechas aleatorias para cada registro. He creado una secuencia de comandos para agregar todos los registros en una lista y luego configurar la lista para filtrar solo los valores únicos:

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)) 

Esto devuelve (en mi tabla de prueba):

[’07 -06-2010 ‘, ’06 -24-2010’, ’07 -05-2010 ‘, ’06 -25-2010’]

Ahora que tengo los valores únicos para el campo “DATE_OBSERVATION”, quiero detectar si:

  • las fechas son únicas (es decir, solo se devuelve una fecha única porque esa es la fecha en cada registro)
  • si las fechas son un rango de fechas (es decir, todas las fechas caen en un rango consecutivo)
  • si las fechas son fechas múltiples, pero no están en un rango de fechas consecutivas

¡Cualquier sugerencia sería muy apreciada! Micro

En lugar de rodar su propia función consecutive , simplemente puede convertir los objetos de fecha en enteros utilizando el método .toordinal() de los objetos de fecha y hora. La diferencia entre el valor máximo y mínimo del conjunto de fechas ordinales es uno más que la longitud del conjunto:

 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" 

Otra versión que usa la misma lógica que en mi otra respuesta.

 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" 

Utilice su base de datos para seleccionar fechas únicas en orden ascendente:

  • Si la consulta devuelve una sola fecha es su primer caso.

  • De lo contrario, averigüe si las fechas son consecutivas:

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

Diseño de código:

 dates =  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 

Aquí está mi versión usando la función reduce ().

 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"