2013-06-01 4 views
63

У меня есть метод python, который принимает ввод даты в виде строки.Как проверить формат строки даты в python?

Как добавить проверку, чтобы убедиться, что строка даты передается методу в ffg. Формат:

'YYYY-MM-DD' 

, если это не так, метод должен поднять какую-то ошибку

+2

Это может быть более Pythonic (просить прощения, а не разрешения) не проверять на всех, и поймать любые результирующие исключения, которые происходят. – Thomas

+0

Связано: [В python, как проверить, действительна ли дата?] (Http://stackoverflow.com/q/9987818/55075) – kenorb

ответ

101
>>> import datetime 
>>> def validate(date_text): 
    try: 
     datetime.datetime.strptime(date_text, '%Y-%m-%d') 
    except ValueError: 
     raise ValueError("Incorrect data format, should be YYYY-MM-DD") 


>>> validate('2003-12-23') 
>>> validate('2003-12-32') 

Traceback (most recent call last): 
    File "<pyshell#20>", line 1, in <module> 
    validate('2003-12-32') 
    File "<pyshell#18>", line 5, in validate 
    raise ValueError("Incorrect data format, should be YYYY-MM-DD") 
ValueError: Incorrect data format, should be YYYY-MM-DD 
+0

Есть ли способ сделать это без попытки/кроме? Python имеет тенденцию значительно замедляться, когда исключение возбуждается и захватывается. – chiffa

+1

@chiffa. Вы можете сопоставить регулярное выражение формата даты, но оно не рекомендуется, потому что оно менее надежное, а исключения понятнее. Вы уверены, что проверка даты - это ваше узкое место? – jamylak

+0

Не совсем, так что в конце концов я просто завершу функцию throw-except в функцию. Я просто удивлен, что нет функции проверки, возвращающей bool, которая запускает бросок Exception в библиотеке datetime. – chiffa

34

Python dateutil библиотека предназначена для этого (и более). Он автоматически преобразует это в объект datetime для вас и поднимет ValueError, если он не сможет.

В качестве примера:

>>> from dateutil.parser import parse 
>>> parse("2003-09-25") 
datetime.datetime(2003, 9, 25, 0, 0) 

Это поднимает ValueError, если дата не отформатирован правильно:

>>> parse("2003-09-251") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Users/jacinda/envs/dod-backend-dev/lib/python2.7/site-packages/dateutil/parser.py", line 720, in parse 
    return DEFAULTPARSER.parse(timestr, **kwargs) 
    File "/Users/jacinda/envs/dod-backend-dev/lib/python2.7/site-packages/dateutil/parser.py", line 317, in parse 
    ret = default.replace(**repl) 
ValueError: day is out of range for month 

dateutil также очень полезно, если вы начинаете необходимости разбирать другие форматы в будущем , так как он может обрабатывать наиболее известные форматы разумно и позволяет вам изменять вашу спецификацию: dateutil parsing examples.

Он также обрабатывает часовые пояса, если вам это нужно.

Обновления на основе комментариев: parse также принимает аргумент dayfirst ключевого слова, которое контролирует день или месяц, ожидается ли прийти первым, если дата неоднозначна. По умолчанию это значение False. Например.

>>> parse('11/12/2001') 
>>> datetime.datetime(2001, 11, 12, 0, 0) # Nov 12 
>>> parse('11/12/2001', dayfirst=True) 
>>> datetime.datetime(2001, 12, 11, 0, 0) # Dec 11 
+0

он может принять слишком много, например., 'parse ('13/12/2001 ')' is "13 Dec", но 'parse ('11/12/2001')' is "12 Nov" (первый результат предполагает «11 Dec» здесь). – jfs

+0

'parse' фактически принимает аргумент ключевого слова' dayfirst', который позволяет вам управлять этим. 'parse ('11/12/2001 ', dayfirst = True)' will return "11 Dec." Значение dateutil по умолчанию - 'dayfirst = False' – Jacinda

+0

, вам не хватает точки, что' datetutil.parser.parse() 'принимает слишком много временных форматов (вы можете найти другие примеры с неоднозначным вводом). Если вы хотите * проверить *, что ваш вход находится в формате ГГГГ-ММ-ДД, функция 'parse()' является неправильным инструментом. – jfs

11
from datetime import datetime 

datetime.strptime(date_string, "%Y-%m-%d") 

..выполняется поднимает ValueError, если он получает несовместимый формат.

..Если вы имеете дело с датами и временем много (в смысле объектов datetime, в отличие от временных меток unix timestamp), неплохо заглянуть в модуль pytz и для хранения/db, хранить все в UTC.

+2

Вы были быстрее, я бы разместил его сам (http://ideone.com/vuxDDf). Upvote. – Tadeck

+0

.. просто увидел это сразу после того, как он был опубликован, и, случается, сегодня работает с объектами datetime. –

6

Я думаю, что полная функция Validate должна выглядеть следующим образом:

from datetime import datetime 

def validate(date_text): 
    try: 
     if date_text != datetime.strptime(date_text, "%Y-%m-%d").strftime('%Y-%m-%d'): 
      raise ValueError 
     return True 
    except ValueError: 
     return False 

Выполнение только

datetime.strptime(date_text, "%Y-%m-%d") 

не хватает, потому что strptime метод не проверяет, что месяц и день месяц - десятичные числа с нулевым запасом. Например,

datetime.strptime("2016-5-3", '%Y-%m-%d') 

будет выполнен без ошибок.

+1

«Вы технически верны - лучший из правильных». Мне нужно было обеспечить это в моих строках. – delrocco

0

Это самый простой способ:

date = datetime.now() 
date = date.strftime('%Y-%m-%d_%H-%M-%S.jpg') 
+0

Неправильный формат даты для заданных вопросов –

Смежные вопросы