web-dev-qa-db-ja.com

Python C#のDateTime.TryParse()に相当するものはありますか?

PythonにC#のDateTime.TryParse()に相当するものはありますか?

形式を推測するという事実ではなく、例外のスローを回避するという事実に言及しています。

25
user541686

例外が必要ない場合は、例外をキャッチします。

try:
    d = datetime.datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
except ValueError:
    d = None

Pythonの禅では、明示的は暗黙的よりも優れています。 strptimealways指定された正確な形式で解析された日時を返します。これは理にかなっています。失敗した場合の動作を定義する必要があるため、本当に必要なのはおそらくです。

except ValueError:
    d = datetime.datetime.now()

または

except ValueError:
    d = datetime.datetime.fromtimestamp(0)

または

except ValueError:
    raise WebFramework.ServerError(404, "Invalid date")

明示的にすることで、フェイルオーバーの動作が何であるかを読む次の人に、それが必要なものであることが明確になります。


または、日付が無効になることはないと確信しているかもしれません。これはデータベースのDATETIME列から取得されます。この場合、キャッチする例外はないため、キャッチしないでください。

_try...catch_複数の日時形式_fmt1,fmt2,...,fmtn_を実行し、不一致のすべての例外(strptimeから)を抑制/処理します(特に、yukky n-deep indentedladderの必要性を回避します) _try..catch_句の)。私は2つのエレガントな方法を見つけました。2つ目は一般的に最適です。 (これは、複数の不一致、不完全、一貫性のない、多言語/地域の日付形式が1つのデータセットに自由に混在することが多い、実際のデータでは大きな問題です。)

1)個々に各形式を適用してみて、個々のstrptime()失敗をNoneの戻り値として処理し、fn呼び出しを連鎖できるようにします...

まず、@ OrWeisの回答からコンパクト化を適応させます。

_def try_strptime_single_format(s, fmt):
    try:
        return datetime.datetime.strptime(s, fmt)
    except ValueError:
        return None
_

これで、try_strptime(s, fmt1) or try_strptime(s, fmt2) or try_strptime(s, fmt3) ...として呼び出すことができますが、これを次のように改善できます。

2)複数の可能な形式を適用し(引数として渡すか、適切なデフォルトを使用する)、それらを繰り返し処理し、エラーを内部でキャッチして処理します:

よりクリーンで、よりシンプルで、よりOOに適した方法は、これを一般化してformatsパラメーターを単一の文字列またはリストにし、それを繰り返し処理することです...呼び出しはtry_strptime(s, [fmt1, fmt2, fmt3, ...])になります。

_def try_strptime(s, fmts=['%d-%b-%y','%m/%d/%Y']):
    for fmt in fmts:
        try:
            return datetime.strptime(s, fmt)
        except:
            continue

    return None # or reraise the ValueError if no format matched, if you prefer
_

(サイドバーとして、_...finally_は必要なドロイドではないことに注意してください。これは、ループの最後ではなく、各ループパスの後に実行されるためです。)

実装2)はよりクリーンで優れていると思います。特に、関数/メソッドはデフォルト形式のリストを格納できるため、実際のデータでのフェイルセーフが向上し、例外が少なくなります。 (他の列に基づいて、どのデフォルト形式を適用するかを推測することもできます。たとえば、最初にドイツ語データでドイツ語の日付形式、アラビア語でアラビア語、ウェブログデータでウェブログの日時形式を試してみてください)

10
smci

これは同等の関数の実装です

import datetime

def try_strptime(s, format):
    """
    @param s the string to parse
    @param format the format to attempt parsing of the given string
    @return the parsed datetime or None on failure to parse 
    @see datetime.datetime.strptime
    """
    try:
        date = datetime.datetime.strptime(s, format)
    except ValueError:
        date = None
    return date
5
Or Weis

いいえ、あなたが求めているのは慣用的なPythonではないので、通常、標準ライブラリにそのようなエラーを破棄する関数はありません。関連する標準ライブラリモジュールはここに文書化されています:

http://docs.python.org/library/datetime.html

http://docs.python.org/library/time.html

解析関数はすべて、無効な入力に対して例外を発生させます。

ただし、他の回答が述べているように、アプリケーション用に作成することはそれほど難しくありません(質問は「Python標準ライブラリ」ではなく「Pythonで」と表現されていたので) 「Pythonで」そのような関数を書く支援が質問に答えているかどうかは明らかではありません)。

4
Eli Stevens

ブルートフォースもオプションです。

def TryParse(datestring, offset):
    nu = datetime.datetime.now()
    retval = nu
    formats = ["%d-%m-%Y","%Y-%m-%d","%d-%m-%y","%y-%m-%d"]  

    if datestring == None:
        retval = datetime.datetime(nu.year,nu.month,nu.day,0,0,0) - datetime.timedelta(offset,0,0,0,0,0,0)
    Elif datestring == '':
        retval = datetime.datetime(nu.year,nu.month,nu.day,0,0,0) - datetime.timedelta(offset,0,0,0,0,0,0) 
    else:
        succes = False
        for aformat in formats:
            try:
                retval = datetime.datetime.strptime(datestring,aformat)
                succes = True
                break
            except:
                pass
        if not succes:
            retval = datetime.datetime(nu.year,nu.month,nu.day,0,0,0) - datetime.timedelta(offset,0,0,0,0,0,0) 
    return retval
2
Jeroen Bom

使用する time.strptime文字列から日付を解析します。

ドキュメント: http://docs.python.org/library/time.html#time.strptime

例: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

#----------------------------- 
# Parsing Dates and Times from Strings

time.strptime("Tue Jun 16 20:18:03 1981")
# (1981, 6, 16, 20, 18, 3, 1, 167, -1)

time.strptime("16/6/1981", "%d/%m/%Y")
# (1981, 6, 16, 0, 0, 0, 1, 167, -1)
# strptime() can use any of the formatting codes from time.strftime()

# The easiest way to convert this to a datetime seems to be; 
now = datetime.datetime(*time.strptime("16/6/1981", "%d/%m/%Y")[0:5])
# the '*' operator unpacks the Tuple, producing the argument list.
0
FogleBird