2012-03-06 257 views
4

我有一个访问表与'日期'字段。它有每个记录的随机日期。我已经建立了一个脚本追加的所有记录到一个列表,然后将列表设置过滤出独特的价值:如何检测Python中的日期是否连续?

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”字段的唯一值,我想检测是否:

  • 日期是单一的(即只有一个唯一的日期是r因为那是每个记录中的日期)
  • 如果日期是日期范围(即,所有日期的陷入连续的范围内)
  • 如果日期是多个日期,但不是在一个范围内的连续日期

任何建议,将不胜感激的! Mike

+1

短懒惰的答复:它们转换成datetime对象,进行排序,然后他们使用'pairwise'配方从'itertools'文档页面的打击下一个日期都比较列表,看它是否是一个范围;对于单日期,取第一天的日期并检查其余所有日期是否在同一日历日内;如果这两者都失败,他们是不同的日期。 – Daenyth 2012-03-06 18:25:13

+1

如果您不选择其他值,请使用'通过date_observation desc'从mytable命令中选择不同的date_observation,并且不要将日期转换为字符串。 – Aprillion 2012-03-06 18:40:59

+0

@deathApril:为什么降序? – jfs 2012-03-06 18:56:45

回答

9

而不是滚动自己的consecutive函数,您可以简单地使用datetime对象的.toordinal()方法将日期对象转换为整数。设定顺序日期的最大值与最小值之差小于设定的长度多了一个:

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" 
+0

谢谢迈克尔。这与我的剧本运作良好!我感谢你的回应。 – Mike 2012-03-06 19:36:43

+0

+1使用一组来消除重复的日期。 – 2012-03-06 19:47:50

+0

@迈克尔狄龙:'选择截然不同的',因为在@ deathpril的评论甚至更好。 – jfs 2012-03-08 19:34:08

0

使用数据库升序选择独特日期:

  • 如果该查询返回一个日期这是你第一种情况

  • 否则找出日期是否是连续的:

    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 
0

这里的使用减少()函数,我的版本。

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

另一个版本使用与我的其他答案相同的逻辑。

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"