Есть ли в Python эквивалент С# DateTime.TryParse()
?
Я имею в виду тот факт, что он избегает исключения, а не тот факт, что он угадывает формат.
Есть ли в Python эквивалент С# DateTime.TryParse()
?
Я имею в виду тот факт, что он избегает исключения, а не тот факт, что он угадывает формат.
Если вы не хотите исключения, перехватите исключение.
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) чище и лучше. В частности, функция/метод может хранить список форматов по умолчанию, что делает его более отказоустойчивым и менее подверженным исключениям в реальных данных. (Мы могли бы даже определить, какие форматы по умолчанию применять на основе других столбцов, например, сначала попробуйте немецкие форматы даты на немецких данных, арабский на арабском, форматы даты и времени в блоге и другие данные)
Нет, то, о чем вы просите, не является идиоматическим Python, и поэтому обычно не будет функций, которые отбрасывают такие ошибки в стандартной библиотеке. Соответствующие стандартные библиотечные модули описаны здесь:
http://docs.python.org/library/datetime.html
http://docs.python.org/library/time.html
Функции синтаксического анализа все вызывают исключения при недопустимом вводе.
Однако, как заявили другие ответы, было бы сложно построить один для вашего приложения (ваш вопрос был сформулирован "в Python", а не "в стандартной библиотеке Python", поэтому неясно, если помощь написана такая функция "в Python" отвечает на вопрос или нет).
Здесь реализация эквивалентной функции
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
Грубая сила также вариант:
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
Используйте 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.
Как насчет 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 способ делать то, что вы хотите.