Есть ли в Python эквивалент C # DateTime.TryParse ()? - PullRequest
20 голосов
/ 07 июля 2011

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

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

Ответы [ 7 ]

22 голосов
/ 08 июля 2011

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

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, столбца, в этом случае не будет исключений для перехвата, и поэтому не перехватывайте его.

9 голосов
/ 19 декабря 2017

Мы хотим try...catch несколько форматов даты и времени fmt1,fmt2,...,fmtn и подавлять / обрабатывать исключения (из strptime) для всех тех, которые не соответствуют (и, в частности, избегать необходимости в юкки-n-глубокой лестнице с отступом try..catch положения). Я нашел два элегантных способа, второй лучше вообще. (Это большая проблема для данных реального мира, где множественные, несовпадающие, неполные, несовместимые и многоязычные / региональные форматы даты часто свободно смешиваются в одном наборе данных.)

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

4 голосов
/ 01 августа 2011

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

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

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

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

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

3 голосов
/ 03 июля 2014

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

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
2 голосов
/ 14 сентября 2014

Грубая сила также опция:

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
0 голосов
/ 07 июля 2011

Используйте 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 голосов
/ 07 июля 2011

Как насчет strptime?

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

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


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

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

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

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

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

...