2012-03-06 101 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"