Предлагает ли python способ легко получить текущую неделю месяца (1:4)?
python - номер недели месяца
Ответы (15)
Чтобы использовать прямое деление, день месяца для просматриваемой даты необходимо скорректировать в соответствии с положением (в пределах недели) первого дня месяца. Итак, если ваш месяц начинается в понедельник (первый день недели), вы можете просто выполнить деление, как было предложено выше. Однако, если месяц начинается в среду, вам нужно добавить 2, а затем выполнить деление. Все это инкапсулировано в функции ниже.
from math import ceil
def week_of_month(dt):
""" Returns the week of the month for the specified date.
"""
first_day = dt.replace(day=1)
dom = dt.day
adjusted_dom = dom + first_day.weekday()
return int(ceil(adjusted_dom/7.0))
adjusted_dom = dom + (1 + first_day.weekday()) % 7
- person user3595632; 05.09.2020
Я знаю, что этому много лет, но я потратил много времени, пытаясь найти этот ответ. Я сделал свой собственный метод и подумал, что должен поделиться.
Модуль календаря имеет метод monthcalendar, который возвращает двумерный массив, где каждая строка представляет неделю. Например:
import calendar
calendar.monthcalendar(2015,9)
результат:
[[0,0,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,0,0,0]]
Итак, numpy, где твой друг здесь. И я в США, поэтому я хочу, чтобы неделя начиналась в воскресенье, а первая неделя была помечена как 1:
import calendar
import numpy as np
calendar.setfirstweekday(6)
def get_week_of_month(year, month, day):
x = np.array(calendar.monthcalendar(year, month))
week_of_month = np.where(x==day)[0][0] + 1
return(week_of_month)
get_week_of_month(2015,9,14)
возвращается
3
datetime.today().year/month/day
:-)
- person Václav; 15.06.2020
Если ваша первая неделя начинается в первый день месяца, вы можете использовать целочисленное деление:
import datetime day_of_month = datetime.datetime.now().day week_number = (day_of_month - 1) // 7 + 1
Ознакомьтесь с пакетом Pendulum
>>> dt = pendulum.parse('2018-09-30')
>>> dt.week_of_month
5
Эта версия может быть улучшена, но в качестве первого взгляда на модули Python (дата, время и календарь) я делаю это решение, надеюсь, оно может быть полезным:
from datetime import datetime
n = datetime.now()
#from django.utils.timezone import now
#n = now() #if you use django with timezone
from calendar import Calendar
cal = Calendar() # week starts Monday
#cal = Calendar(6) # week stars Sunday
weeks = cal.monthdayscalendar(n.year, n.month)
for x in range(len(weeks)):
if n.day in weeks[x]:
print x+1
now
переменная?
- person user1234440; 01.06.2020
Ознакомьтесь с модулем python календаря.
st, end = calendar.monthrange(2012, 6)
, days = range(st, end+1)
, week_days = [days[i : i+7] for i in range(0, len(days), 7)]
- person Droogans; 06.06.2012
Ответ Джоша нужно немного изменить, чтобы он соответствовал первому дню, выпавшему на воскресенье.
def get_week_of_month(date):
first_day = date.replace(day=1)
day_of_month = date.day
if(first_day.weekday() == 6):
adjusted_dom = (1 + first_day.weekday()) / 7
else:
adjusted_dom = day_of_month + first_day.weekday()
return int(ceil(adjusted_dom/7.0))
Я нашел довольно простой способ:
import datetime
def week(year, month, day):
first_week_month = datetime.datetime(year, month, 1).isocalendar()[1]
if month == 1 and first_week_month > 10:
first_week_month = 0
user_date = datetime.datetime(year, month, day).isocalendar()[1]
if month == 1 and user_date > 10:
user_date = 0
return user_date - first_week_month
возвращает 0, если первая неделя
isocalendar()
может вернуть 53 для 1 января. Ваша реализация возвращает -52 для weekOfMonth(2010, 1, 8)
.
- person Adam Rosenfield; 07.12.2010
Ответ Джоша кажется лучшим, но я думаю, что мы должны учитывать тот факт, что неделя принадлежит месяцу только в том случае, если ее четверг приходится на этот месяц. По крайней мере, это что говорит iso.
По этому стандарту в месяце может быть до 5 недель. День может принадлежать месяцу, но неделя, которой он принадлежит, может не принадлежать.
Я принял во внимание, что просто добавив простой
if (first_day.weekday()>3) :
return ret_val-1
else:
return ret_val
где ret_val — точно вычисленное значение Джоша. Протестировано в июне 2017 г. (имеет 5 недель) и в сентябре 2017 г. Передача «2017-09-01» возвращает 0, поскольку этот день принадлежит неделе, которая не принадлежит сентябрю.
Наиболее правильным было бы, чтобы метод возвращал и номер недели, и название месяца, к которому принадлежит введенный день.
def week_of_month(date_value):
return (date_value.isocalendar()[1] - date_value.replace(day=1).isocalendar()[1] + 1)
date_value должен быть в формате метки времени. Это даст идеальный ответ во всех случаях.
Вариант ответа @Manuel Solorzano:
from calendar import monthcalendar
def get_week_of_month(year, month, day):
return next(
(
week_number
for week_number, days_of_week in enumerate(monthcalendar(year, month), start=1)
if day in days_of_week
),
None,
)
E.g.:
>>> get_week_of_month(2020, 9, 1)
1
>>> get_week_of_month(2020, 9, 30)
5
>>> get_week_of_month(2020, 5, 35)
None
Скажем, у нас есть календарь на месяц следующим образом:
Mon Tue Wed Thur Fri Sat Sun
1 2 3
4 5 6 7 8 9 10
Мы говорим, что день 1–3 относится к неделе 1, а день 4–10 относится к неделе 2 и т. д.
В этом случае я считаю, что week_of_month для определенного дня следует рассчитывать следующим образом:
import datetime
def week_of_month(year, month, day):
weekday_of_day_one = datetime.date(year, month, 1).weekday()
weekday_of_day = datetime.date(year, month, day)
return (day - 1)//7 + 1 + (weekday_of_day < weekday_of_day_one)
Однако, если вместо этого мы хотим получить n-й день недели, которым является эта дата, например, день 1 — это 1-я пятница, день 8 — это 2-я пятница, а день 6 — это 2-я пятница. 1-я среда, то мы можем просто вернуть (day - 1)//7 + 1
Это должно сделать это.
#! /usr/bin/env python2
import calendar, datetime
#FUNCTIONS
def week_of_month(date):
"""Determines the week (number) of the month"""
#Calendar object. 6 = Start on Sunday, 0 = Start on Monday
cal_object = calendar.Calendar(6)
month_calendar_dates = cal_object.itermonthdates(date.year,date.month)
day_of_week = 1
week_number = 1
for day in month_calendar_dates:
#add a week and reset day of week
if day_of_week > 7:
week_number += 1
day_of_week = 1
if date == day:
break
else:
day_of_week += 1
return week_number
#MAIN
example_date = datetime.date(2015,9,21)
print "Week",str(week_of_month(example_date))
#Returns 'Week 4'
Перейти к последнему дню недели в месяце и разделить на 7
from math import ceil
def week_of_month(dt):
""" Returns the week of the month for the specified date.
"""
# weekday from monday == 0 ---> sunday == 6
last_day_of_week_of_month = dt.day + (7 - (1 + dt.weekday()))
return int(ceil(last_day_of_week_of_month/7.0))
Искомый ответ: (dm-dw+(dw-dm)%7)/7+1
, где dm
— день месяца, dw
— день недели, а %
— положительный остаток.
Это происходит из соотношения смещения месяца (mo
) и недели месяца (wm
), где смещение месяца — это то, как далеко в неделе начинается первый день. Если мы считаем, что все эти переменные начинаются с 0, мы имеем
wm*7+dw = dm+mo
Вы можете решить это по модулю 7 для mo
, так как это приводит к тому, что переменная wm
выпадает, поскольку она появляется только как кратная 7
dw = dm+mo (%7)
mo = dw-dm (%7)
mo = (dw-dm)%7 (since the month offset is 0-6)
Затем вы просто подставляете смещение месяца в исходное уравнение и решаете для wm
wm*7+dw = dm+mo
wm*7 = dm-dw + mo
wm*7 = dm-dw + (dw-dm)%7
wm = (dm-dw + (dw-dm)%7) / 7
Поскольку dm
и dw
всегда являются парными, они могут быть смещены на любую величину, поэтому переключение всего, чтобы начать с 1, только меняет уравнение на (dm-dw + (dw-dm)%7)/7 + 1
.
Конечно, библиотека python datetime
начинается с dm
с 1 и dw
с 0. Итак, если предположить, что date
является объектом datatime.date
, вы можете пойти с
(date.day-1-date.dayofweek() + (date.dayofweek()-date.day+1)%7) / 7 + 1
Поскольку внутренний бит всегда кратен 7 (это буквально dw*7
), вы можете видеть, что первый -date.dayofweek()
просто корректирует значение в обратном направлении до ближайшего кратного 7. Целочисленное деление тоже делает это, поэтому его можно еще упростить до
(date.day-1 + (date.dayofweek()-date.day+1)%7) // 7 + 1
Имейте в виду, что dayofweek()
помещает воскресенье в конец недели.