Как потребовать, чтобы временная метка была заполнена нулями во время проверки в Python?
Я пытаюсь проверить строку, которая должна содержать временную метку в формате ISO 8601 (обычно используется в JSON).
Python strptime
кажется очень прощающим, когда дело доходит до проверки нулевого заполнения, см. пример кода ниже (обратите внимание, что в часе отсутствует нулевой уровень):
>>> import datetime
>>> s = '1985-08-23T3:00:00.000'
>>> datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
datetime.datetime(1985, 8, 23, 3, 0)
Он грациозно принимает строку, которая, например, не заполняется нулями в течение часа, и не генерирует исключение ValueError
, как я ожидал.
Есть ли способ принудительно использовать strptime для проверки того, что он заполнен нулями? Или есть ли какая-либо другая встроенная функция в стандартных libs Python, которая делает?
Я бы не хотел писать свой собственный regexp
для этого.
Ответы
Ответ 1
Уже есть ответ, что синтаксический анализ ISO8601 или RFC3339 даты/времени с помощью Python strptime() невозможен: Как разобрать дату в формате ISO 8601?
Итак, чтобы ответить на ваш вопрос, нет никакой возможности в стандартной библиотеке Python для надежного анализа такой даты.
Что касается предложений регулярного выражения, строка даты, например
2020-14-32T45:33:44.123
приведет к допустимой дате. Существует много модулей Python (если вы ищете "iso8601" на https://pypi.python.org), но для создания полного ISO8601 Validator потребуются такие вещи, как прыжок секунд, список возможных значений смещения часового пояса и многое другое.
Ответ 2
Вы сказали, что хотите избежать регулярного выражения, но на самом деле это тип проблемы, когда регулярное выражение подходит. Как вы обнаружили, strptime
очень гибко относится к вводу, который он примет. Однако регулярное выражение для этой проблемы относительно легко составить:
import re
date_pattern = re.compile(r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}')
s_list = [
'1985-08-23T3:00:00.000',
'1985-08-23T03:00:00.000'
]
for s in s_list:
if date_pattern.match(s):
print "%s is valid" % s
else:
print "%s is invalid" % s
Выход
1985-08-23T3:00:00.000 is invalid
1985-08-23T03:00:00.000 is valid
Попробуйте на repl.it
Ответ 3
Чтобы принудительно выполнить strptime
для проверки ведущих нулей для вас, вам придется добавить свои собственные литералы в Python _strptime._TimeRE_cache
. Решение очень хакерское, скорее всего, не очень портативное и требует записи RegEx - хотя и только для часовой части отметки времени.
Другим решением проблемы было бы написать свою собственную функцию, которая использует strptime
, а также преобразует обработанную дату в строку и сравнивает две строки. Это решение переносимо, но ему не хватает четких сообщений об ошибках - вы не сможете отличить отсутствующие ведущие нули в часах, минутах, секундах.
Ответ 4
Единственное, что я могу думать о том, чтобы не вмешиваться в внутренние компоненты Python, - это проверить правильность формата, зная, что вы ищете.
Итак, если я правильно ее заработал, формат '%Y-%m-%dT%H:%M:%S.%f'
и должен быть нулевым.
Затем вы знаете точную длину строки, которую вы ищете, и воспроизведите предполагаемый результат.
import datetime
s = '1985-08-23T3:00:00.000'
stripped = datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
try:
assert len(s) == 23
except AssertionError:
raise ValueError("time data '{}' does not match format '%Y-%m-%dT%H:%M:%S.%f".format(s))
else:
print(stripped) #just for good measure
>>ValueError: time data '1985-08-23T3:00:00.000' does not match format '%Y-%m-%dT%H:%M:%S.%f