Есть ли Python, эквивалентный C# DateTime.TryParse()?

Есть ли эквивалент C# DateTime.TryParse() в питоне?

Я имею в виду тот факт, что он избегает исключения, а не тот факт, что он угадывает формат.

7 ответов

Если вы не хотите исключения, поймайте исключение.

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

В дзен Python явное лучше, чем неявное. strptime всегда возвращает дату и время, проанализированные в указанном формате. Это имеет смысл, потому что вы должны определить поведение в случае сбоя, возможно, то, что вы действительно хотите.

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) для всех тех, кто не соответствует (и, в частности, избегать необходимости в юкки n-глубокая лестница с отступами try..catch положения). Я нашел два элегантных способа, второй лучше вообще. (Это большая проблема для данных реального мира, где множественные, несовпадающие, неполные, несовместимые и многоязычные / региональные форматы даты часто свободно смешиваются в одном наборе данных.)

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) чище и лучше. В частности, функция / метод может хранить список форматов по умолчанию, что делает его более отказоустойчивым и менее благоприятным для исключений в реальных данных. (Мы могли бы даже определить, какие форматы по умолчанию применять на основе других столбцов, например, сначала попробуйте немецкие форматы даты на немецких данных, арабский на арабском, форматы даты и времени в блоге и другие данные)

Вот эквивалентная реализация функции

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

Нет, то, что вы просите, это не идиоматический Python, и поэтому в стандартной библиотеке обычно не будет функций, которые отбрасывают подобные ошибки. Соответствующие стандартные модули библиотеки описаны здесь:

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

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

Все функции синтаксического анализа вызывают исключения при неверном вводе.

Тем не менее, как уже говорилось в других ответах, было бы не очень сложно создать его для вашего приложения (ваш вопрос был сформулирован "в Python", а не "в стандартной библиотеке Python"), поэтому неясно, поможет ли в написании такой функции "в Python" отвечает на вопрос или нет).

Грубая сила также вариант:

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

Я согласен, что tryparse - очень полезная функция на С #. К сожалению, нет эквивалентной прямой функции этого в python (может быть, я не знаю). Я считаю, что вы хотите проверить, является ли строка датой или нет, не беспокоясь о формате даты. Моя рекомендация пойти наpandas to_datetime функция:

def is_valid_date(str_to_validate: str) -> bool:
    try:
        if pd.to_datetime(str_to_validate):
            return True
        else:
            return False
    except ValueError:
        return False

Использование time.strptime разобрать даты из строк.

Документация: http://docs.python.org/library/time.html

Примеры из: 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.

Как насчет strptime?

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

Он выдаст ValueError, если не сможет проанализировать строку на основе предоставленного формата.


Редактировать:

Так как вопрос был отредактирован, чтобы включить бит об исключениях после того, как я ответил на него. Я хотел добавить примечание об этом.

Как указывалось в других ответах, если вы не хотите, чтобы ваша программа вызывала исключение, вы можете просто перехватить его и обработать:

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

Это Pythonic способ делать то, что вы хотите.

Другие вопросы по тегам