Python: количество недель в месяце
при указании даты:
datetime.datetime(2011, 8, 15)
Как я могу узнать, что это третья недели месяца?
что если я хочу этой даты?
datetime.datetime(2011, 2, 28) //should return 4
datetime.datetime(2011, 8, 29) //should return 5
Я понимаю, что только февраль имеет 4 недели, Если данная дата находится в високосном году (bissextile)
7 ответов
In [115]: d=datetime.datetime(2011, 2, 28)
In [116]: (d.day-1)//7+1
Out[116]: 4
In [117]: d=datetime.datetime(2011, 8, 29)
In [118]: (d.day-1)//7+1
Out[118]: 5
подход по модулю, показанный в других ответах, может вводить в заблуждение. Представьте себе недели в году. Есть 52 куска 7 дней в любом 365-дневном году, с одним днем, оставшимся. Итак, если для моего первого года 52-я неделя заканчивается 30 декабря, и мне остается беспокоиться о 31 декабря.
Я могу или считайте, что в году 53 недели, а 53-я неделя-31 декабря, 1 января, 2 января, 3 января ... Или, более условно, я считаю, что первая неделя следующей год фактически начинается 31 декабря. Вот как это делает ваш дневник pocket book.
точно такая же логика применяется к месяцам, однако ее может быть труднее обнаружить. К сожалению, вы выбираете август 2011, который имеет аккуратное расположение начала 1-го числа месяца в понедельник.
>>> print calendar.month(2011,8)
August 2011
Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
>>> print calendar.month(2011,9)
September 2011
Mo Tu We Th Fr Sa Su
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
таким образом, 29 сентября будет, по простому числу деления дней на 7 подход, быть в 5-ю неделю если 1-4 сентября приходится на август, то 29 сентября приходится на 4-ю неделю сентября.
все зависит от вашего определения того, когда начинается Неделя.
import datetime
import calendar
# I am assuming that the first week of a month starts with the first monday of a month...
#I *think* my logic is OK - if Monday (0) is the start of the week, then
#any dayof the month minus its own day of week (0,1,2...) must be positive
#if that day is on or after the first monday of the month
def week_of_month(tgtdate):
days_this_month = calendar.mdays[tgtdate.month]
for i in range(1, days_this_month):
d = datetime.date(tgtdate.year, tgtdate.month, i)
if d.day - d.weekday() > 0:
startdate = d
break
# now we canuse the modulo 7 appraoch
return (tgtdate - startdate).days //7 + 1
tgtdates = [datetime.date(2011, 8, 29),
datetime.date(2011, 8, 1)
]
for tgtdate in tgtdates:
print tgtdate,
print "is in week %s" % week_of_month(tgtdate)
print calendar.month(tgtdate.year,tgtdate.month)
# 2011-09-29 is in week 4
# 2011-09-01 is in week 0
# September 2011
# Mo Tu We Th Fr Sa Su
# 1 2 3 4
# 5 6 7 8 9 10 11
# 12 13 14 15 16 17 18
# 19 20 21 22 23 24 25
# 26 27 28 29 30
# 2011-08-29 is in week 5
# 2011-08-01 is in week 1
# August 2011
# Mo Tu We Th Fr Sa Su
# 1 2 3 4 5 6 7
# 8 9 10 11 12 13 14
# 15 16 17 18 19 20 21
# 22 23 24 25 26 27 28
# 29 30 31
выше, неделя 0 означает, что неделя не считается частью этого месяца. Итак, 1 сентября-5 августа.
NB
Я хотел бы прокомментировать ответ @unutbu, но у меня недостаточно очков, я думаю. Подход по модулю 7 терпит неудачу в сентябре 2011 года.
>>> d = datetime.date(2011,9,28)
>>> (d.day-1)//7+1
4
>>> d = datetime.date(2011,9,1)
>>>
>>> (d.day-1)//7+1
1
из вышеприведенного календаря 1 сентября находится на первой неделе, но это означает, что 28-е не может быть на 4 - й неделе-это должно быть либо на 5-й неделе, либо 1-й на 0-й неделе...
Это (немного корявый), например, с помощью модуля "календарь"...
import calendar
import datetime
def week(dt):
mth = calendar.monthcalendar(dt.year, dt.month)
for i, wk in enumerate(mth):
if dt.day in wk:
return i + 1
calendar.setfirstweekday(calendar.MONDAY)
week(datetime.datetime(2011, 8, 15)) # 3
week(datetime.datetime(2011, 2, 28)) # 5
week(datetime.datetime(2011, 8, 29)) # 5
... получает неправильный ответ на 2011-02-28, основываясь на ожиданиях ОП, Если недели не начнутся во вторник.
может быть http://labix.org/python-dateutil поможет.
кроме этого, это просто математика.
from datetime import datetime, timedelta
def week_of_month(date):
month = date.month
week = 0
while date.month == month:
week += 1
date -= timedelta(days=7)
return week
Как насчет этого. Мы даем дату, на которую мы хотим найти неделю. Мы сбрасываем дату в первый день месяца в новой переменной. Затем мы создаем неделю в году как для первого дня, так и для заданной даты. Вычесть первый isoweek из isoweek данной даты и добавить один. Вы добавляете один, чтобы исправить нулевой индекс. Это должно дать номер недели в месяце.
import datetime
def _get_week_of_day(date):
first_day = date.replace(day=1)
iso_day_one = first_day.isocalendar()[1]
iso_day_date = date.isocalendar()[1]
adjusted_week = (iso_day_date - iso_day_one) + 1
return adjusted_week
testdate = datetime.datetime(2011, 2, 28)
weekofmonth = (testdate.day+7-1)/7
В общем найти потолок деления: потолок (x/y) = (x+y-1) / y
чтобы учесть комментарий @Usagi:
datetime.datetime(2011, 8, 15) // should return 3
datetime.datetime(2011, 2, 28) // should return 5
datetime.datetime(2011, 8, 29) // should return 5
следующее уравнение управляет тем, что первый день месяца не нужен понедельник:
(d.day-d.weekday() -2)//7+2
-2 и +2 позволяют получить номер недели между 1 и 6