Есть ли 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 способ делать то, что вы хотите.