2016-09-02 18 views
5

有什麼辦法可以比較兩個日期而不用每次在python中調用strptime?我確定給我的問題沒有其他辦法,但要確保我已經檢查了所有選項。用於比較日期的替代方案?

我正在瀏覽一個非常大的日誌文件,每一行都有一個日期,我需要比較以查看該日期是否在兩個其他日期的範圍內。我不得不將每行的每個日期與導致很大瓶頸的strptime轉換;

Fri Sep 2 15:12:43 2016 output2.file 

     63518075 function calls (63517618 primitive calls) in 171.409 seconds 

    Ordered by: cumulative time 
    List reduced from 571 to 10 due to restriction <10> 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.003 0.003 171.410 171.410 script.py:3(<module>) 
     1 0.429 0.429 171.367 171.367 scipt.py:1074(main) 
     1 3.357 3.357 162.009 162.009 script.py:695(get_data) 
    1569898 14.088 0.000 141.175 0.000 script.py:648(check_line) 
    1569902 6.899 0.000 71.706 0.000 {built-in method strptime} 
    1569902 31.198 0.000 64.805 0.000 /usr/lib64/python2.7/_strptime.py:295(_strptime) 
    1569876 15.324 0.000 43.170 0.000 script.py:626(dict_add) 
    4709757 23.370 0.000 23.370 0.000 {method 'strftime' of 'datetime.date' objects} 
    1569904 1.655 0.000 18.799 0.000 /usr/lib64/python2.7/_strptime.py:27(_getlang) 
    1569899 2.103 0.000 17.452 0.000 script.py:592(reverse) 

日期格式化爲這樣;

current_date = 01/Aug/1995:23:59:53 

我正在比較他們這樣;

with open(logfile) as file: 
    for line in file: 
     current_date = strptime_method(line) 
     if current_date => end_date: 
      break 

當談到比較日期時,是否有其他選擇?

編輯:謝謝大家,特別是user2539738。根據他/她的建議,結果如下:大速差;

Fri Sep 2 16:14:59 2016 output3.file 

     24270567 function calls (24270110 primitive calls) in 105.466 seconds 

    Ordered by: cumulative time 
    List reduced from 571 to 10 due to restriction <10> 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.002 0.002 105.466 105.466 script.py:3(<module>) 
     1 0.487 0.487 105.433 105.433 script.py:1082(main) 
     1 3.159 3.159 95.861 95.861 script.py:702(get_data) 
    1569898 21.663 0.000 77.138 0.000 script.py:648(check_line) 
    1569876 14.979 0.000 43.408 0.000 script.py:626(dict_add) 
    4709757 23.865 0.000 23.865 0.000 {method 'strftime' of 'datetime.date' objects} 
    1569899 1.943 0.000 15.556 0.000 script.py:592(reverse) 
     1 0.000 0.000 9.078 9.078 script.py:1066(print_data) 
     1 0.021 0.021 9.044 9.044 script.py:1005(print_ip) 
     10 0.001 0.000 7.067 0.707 script.py:778(ip_api) 
+1

如果輸入的日誌記錄按日期排序,你可能沒有檢查每一個日誌記錄在日期範圍內,並且可能可以執行二分搜索以確定您的範圍的開始和結束記錄。只是想法。 – alecxe

+0

什麼是'strptime_method'?你自己的一些代碼?另外,你使用'time'(用於處理日期和時間的功能模塊)還是'datetime'(基於類的模塊)? –

+1

@alecxe這就是我目前已經做的。如果發現日期超出範圍,它將從循環中斷。但是如果你的範圍很大,那麼我的結果顯示,這可能會很耗時,主要是因爲每行被調用的方法太糟糕。 – user1165419

回答

1

我假設CURRENT_DATE是一個字符串

首先,字典

moDict = {"Aug":8, "Jan":1} #etc 

然後,找到年/月/日等

current_date = "01/Aug/1995:23:59:53" 

Yr = int(current_date[7:11]) 
Mo = moDict[(current_date[3:6])] 
Day = int(current_date[0:2]) 

m_date = datetime.datetime(Yr,Mo,Day) 

,你可以用它來比較

+0

我會毫不驚訝地發現'strptime'已經在內部完成了。你真的測試過速度嗎? –

+0

@DavidHeyman檢查我的結果 – user1165419

+0

@DavidHeyman即使'strptime'在內部執行此操作,它也必須解釋格式字符串。另一方面,它不需要解釋Python。 :) – Kaz

1

由於您的日期顯示爲固定長度格式,因此分析起來非常簡單,您不需要strptime即可完成此操作。您可以將它們重新排列到ISO 8601 date/time format中,並將它們直接作爲字符串進行比較!

mos = {'Jan': '01', 'Feb': '02', 'Mar': '03', 'Apr': '04', 'May': '05', 'Jun': '06', 'Jul': '07', 'Aug': '08', 'Sep': '09', 'Oct': '10', 'Nov': '11', 'Dec': '12'} 

def custom_to_8601(dt): 
    return dt[7:11] + '-' + mos[dt[3:6]] + '-' + dt[0:2] + 'T' + dt[12:] 

>>> custom_to_8601('01/Aug/1995:23:59:53') 
'1995-08-01T23:59:53' 

這可能是一個觸摸更快地使用join而不是字符串連接,並離開了標點符號:

def comparable_date(dt): 
    return ''.join([dt[7:11], mos[dt[3:6]], dt[0:2], dt[12:]]) 

>>> comparable_date('01/Aug/1995:23:59:53') 
'1995080123:59:53' 

運行cProfile上百萬重複對我產生這些時間:

  • custom_to_8601:0.978秒
  • comparable_date:0.937秒
  • 你原來的代碼strptime:15.492秒
  • 使用datetime構造較早的答案:1.134秒
+0

謝謝,我要試試這個,並在我的結果中回覆你! – user1165419