2016-09-02 5 views
5

Pythonで毎回strptimeを呼び出さずに2つの日付を比較する方法はありますか?私の問題は他の方法はありませんが、私はすべてのオプションをチェックしていることを確認したいと考えています。日付比較のstrptimeの代わりに?

私は非常に大きなログファイルを調べています。各行には、その日付が2つの他の日付の範囲内にあるかどうかを比較する必要がある日付があります。私は大きなボトルネックの原因となっている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です。ここに彼/彼女の提案に基づく結果は、大きな速度差;私はCURRENT_DATEを想定してい

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これは私が現在行っていることです。範囲外の日付が検出された場合は、ループから切り離されます。しかし、あなたの範囲がかなり大きい場合、主に呼び出される各行のstrptimeメソッドのために、私の結果が示すように時間がかかることがあります。 – user1165419

答えて

1

は、辞書

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 1000000の繰り返しを実行すると、これらのタイミングを生成しますcustom_to_8601:0.978秒

  • comparable_date:0.937秒
  • strptimeであなたの元のコード:15.492秒
  • datetimeコンストラクタを使用して、以前の回答:入力ログレコードを日付順に並んでいた場合は1.134秒
+0

ありがとう、私はこれを試してみると、私の結果であなたに戻ってくる! – user1165419