Reputation: 1212
I'm converting a date string using the following (not the full code, just the relevant bit):
str_format = '%Y-%m-%d %H:%M:%S'
datetime.strptime('2015-13-23 13:43:23', str_format)
This throws a "time data does not match format" because the month is wrong (13 is not a valid month).
I was wondering if it was possible to have it raise an exception on the month (or day) being invalid instead of the format not matching because of the invalid date? The following clearly shows that datetime can determine that:
>>> print datetime(2015, 13, 23)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: month must be in 1..12
Upvotes: 4
Views: 4314
Reputation: 51847
You could always parse the text and then use it to construct a datetime yourself - or pre-validate it if that suits you:
from datetime import datetime
def to_datetime(date_string):
year = int(date_string[0:4])
month = int(date_string[5:7])
day = int(date_string[8:10])
return datetime(year, month, day)
print(to_datetime('2015-13-23 13:42:13'))
Throws:
Traceback (most recent call last):
File "test.py", line 11, in <module>
print(to_datetime('2015-13-23 13:42:13'))
File "test.py", line 9, in to_datetime
return datetime(year, month, day)
ValueError: month must be in 1..12
If you want to know how datetime
does it - Use the Source, Luke!
>>> import datetime
>>> datetime.__file__
'/usr/lib/python3.5/datetime.py'
Open that file and you'll find:
def _check_date_fields(year, month, day):
year = _check_int_field(year)
month = _check_int_field(month)
day = _check_int_field(day)
if not MINYEAR <= year <= MAXYEAR:
raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
if not 1 <= month <= 12:
raise ValueError('month must be in 1..12', month)
dim = _days_in_month(year, month)
if not 1 <= day <= dim:
raise ValueError('day must be in 1..%d' % dim, day)
return year, month, day
Upvotes: 1
Reputation: 2743
I feel like there are two ways to approach this:
Way 1
str_format = '%Y-%m-%d %H:%M:%S'
try:
datetime.strptime('2015-13-23 13:43:23', str_format)
except ValueError:
raise ValueError("Something went wrong")
The downside to this is that it's not constrained to only situations where the month or day are wrong, as your question initially asked.
Way 2
import calendar
str_format = '%Y-%m-%d %H:%M:%S'
datetime_str = '2015-13-23 13:43:23'
year = int(datetime_str[0:4])
month = int(datetime_str[5:7])
day = int(datetime_str[8:10])
cal = calendar.Calendar(6)
if not 1 <= month <= 12:
raise ValueError("wrong month")
else:
days_list = list(cal.itermonthdays(year, month))
if day not in days_list:
raise ValueError("invalid day")
If you want to use the generator without converting to a list
....
if not 1 <= month <= 12:
raise ValueError("wrong month")
days_gen = cal.itermonthdays(year, month)
for gen_day in days_gen:
if gen_day == day:
break
else:
raise ValueError("wrong day")
Upvotes: 0