Подход по модулю, показанный в других ответах, может вводить в заблуждение. Представьте себе недели в году. Есть 52 куска по 7 дней в любой 365-дневный год, с одним оставшимся днем. Так что если в течение моего первого года 52-я неделя заканчивается 30 декабря, и у меня остается 31 декабря, чтобы волноваться.
Я мог бы либо считать, что в году 53 недели, а 53 неделю - 31 декабря, 1 января, 2 января, 3 января ... Или, более условно, я считаю, что первая неделя следующего года фактически начинается 31 декабря. Вот как это делает ваш дневник.
Конечно, это означает, что в следующем году 52-я неделя заканчивается не 30 декабря, а 29 декабря.
И каждый год происходит спад по одному за раз, до 6-го года, когда мы переместили конец 52-й недели назад на 6 дней (и бросили в високосный день для хорошей меры), так что вся 1-я неделя 2017 года будет содержится в 2016 году, и это было бы глупо. Таким образом, в 2016 году будет 53 недели.
Точно такая же логика применима к месяцам, однако это может быть сложнее обнаружить. К сожалению, вы выбираете август 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 августа на 5-й неделе августа, но с той же логикой 1-е, 2-е, 3-е и 4-е сентября также будут на 5-й неделе августа, и поэтому не могут быть на 1-й неделе сентября.
Таким образом, 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 ...