2013-02-28 4 views
3

Я нашел очень полезный объект datetime.datetime при работе с датами, однако теперь у меня есть ситуация, когда datime.datetime не работает для меня. Во время выполнения программы поле дня динамически вычисляется и вот проблема:datetime.datetime - поле дня за пределами допустимого диапазона

>>> datetime.datetime(2013, 2, 29, 10, 15) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: day is out of range for month 

OK, февраль не 29 дней, но было бы здорово, если бы даты и времени может понять это и вернуть этот объект

datetime.datetime(2013, 3, 1, 10, 15) 

Какой самый лучший способ решить эту ситуацию? Итак, я ищу общее решение, когда аргумент дня больше, чем может быть в течение нескольких дней.

+5

Нет, это было бы * не * быть большим. Явный лучше, чем неявный. –

+0

Вы не можете получить общее решение для исправления ломаной логики. Вы можете попробовать использовать 'import calendar; calendar.monthrange (год, месяц) ', чтобы получить месячные дни. – dmg

ответ

3

В то время как есть много говорить об использовании try...except в этой ситуации, если вам нужно на самом деле только месяц + daysOffset вы можете сделать это:

d = datetime.datetime(targetYear,targetMonth,1,hour,min,sec) 
d = d + datetime.timedelta(days=targetDayOfMonth-1) 

В принципе, установить день месяца до 1, который всегда находится в месяце, затем добавьте timedelta для возврата соответствующей даты в текущем или будущем месяце.

d = datetime.datetime(2013, 2, 1, 10, 15) # day of the month is 1 
# since the target day is the 29th and that is 28 days after the first 
# subtract 1 before creating the timedelta. 
d = d + datetime.timedelta(days=28) 
print d 
# datetime.datetime(2013, 3, 1, 10, 15) 
+0

Это работает для меня, спасибо. – Zed

6

От Zen of Python: Явный лучше, чем неявный. Когда вы делаете ошибку, например, пытаетесь создать недопустимую дату, вам необходимо явно обработать эту ситуацию.

Как вы справляетесь с этим исключением полностью до вашего приложения. Вы можете сообщить конечным пользователям об ошибке, или вы можете попытаться перевести дни в следующий месяц или ограничить день до последнего юридического дня в текущем месяце. Все будут действительными вариантами, в зависимости от ваших вариантов использования.

Следующий код перенесет «излишки» дней на следующий месяц. Поэтому 2013-02-30 вместо этого станет 2013-03-02.

import calendar 
import datetime 

try: 
    dt = datetime.datetime(year, month, day, hour, minute) 
except ValueError: 
    # Oops, invalid date. Assume we can fix this by shifting this to the next month instead 
    _, monthdays = calendar.monthrange(year, month) 
    if monthdays < day: 
     surplus = day - monthdays 
     dt = datetime.datetime(year, month, monthdays, hour, minute) + datetime.timedelta(days=surplus) 
1

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

datetime.datetime(targetYear, targetMonth+1, 1) + dt.timedelta(days = -1) 
Смежные вопросы