我正在尝试利用Python的
calendar
模块来计算特定年份中特定工作日的数量。
例如,2020 年星期一的数量。
我遇到的问题是结果比任何类型输入的结果大约多 10 左右。这是我的代码:
import calendar
class MyCalendar(calendar.Calendar):
def __init__(self):
self.setfirstweekday(calendar.SUNDAY)
def count_weekday_in_year(self, year, weekday):
counter = 0
yearDays = []
for x in range(1,13):
yearDays.append(list(self.monthdays2calendar(year, x)))
print("Working on the following list: \n", yearDays)
for x in yearDays:
for y in x:
for z in y:
if z[1] == weekday:
counter+=1
return counter
mc = MyCalendar()
print(mc.count_weekday_in_year(2000, 6))
例如,
year=2000, weekday=6
应该返回 53,但我得到 64。
我知道我有一个计数错误。我只是不知道在哪里。我也知道我导航列表多层的方式并不是最理想的。
如何计算给定年份中工作日出现次数的算法实际上并不需要迭代。这只是一个从工作日第一次出现开始找出一年中的部分适合多少周的问题。
您需要的信息:
您可以使用
计算所选日期的第一次(从零开始)出现offset = (selected_day - first_weekday_of_year) % length_of_week
这在 python 中是开箱即用的,因为模 (
%
) 的结果始终采用 python 中第二个操作数的符号。
所选日期出现的次数将是您可以放入的周数
length_of_year - offset
,但您只需偏移一,因为您是从所选日期开始的:
occurrences = 1 + (length_of_year - offset - 1) // length_of_week
疯狂物理学家的预感绝对正确。 Monthdays2calendar() 给出完整的周,包括属于下个月的天数,但落在包含本月中的天数的一周内。 如果您适当地命名变量,它有助于跟踪事物,因此我对循环进行了一些修改。除此之外,另一件重要的事情是,在日历库中,给定月份之外的日期被赋予“0”作为其“月份中的日期”索引 - 因此为了正确解释这一点,我们需要排除“一个月中的某一天”等于零的任何天,如下所示:
for month in yearDays:
for week in month:
for day_of_month, day_of_week in week:
if day_of_month == 0:
continue
if day_of_week == weekday:
counter+=1
完成此更改后,我们看到程序的最终输出为 53
2020年适用于周一的通用解决方案:
import datetime
def count_weekdays(year: int, target_weekday: int):
d = datetime.date(year, 1, 1)
d += datetime.timedelta(days=(target_weekday - d.weekday()) % 7)
time_span = datetime.date(year, 12, 31) - d
return (time_span // 7).days + 1
# monday == 0 (see https://docs.python.org/3/library/datetime.html#datetime.date.weekday)
mondays_in_2020 = count_weekdays(2020, 0) # 52
为了查找一年中星期一或星期日的数量,我使用了这个,其中数据是从 Monthdays2calendar(year, Month) 生成的列表。(包含 7 个元组的列表 [(0, 0), (0, 1), ( 0, 2), (0, 3), (0, 4), (1, 5), (2, 6)])。如果任何元组的第一个元素为 0,则表示该天是从上个月或下个月开始生成的,以完成一周,因此该 element[0] = 0 不应该被计数。
import calendar
class MyCalendar(calendar.Calendar):
def __init__(self):
self.setfirstweekday(calendar.MONDAY)
def count_weekday_in_year(self, year, weekday):
counter = 0
for month in range(1,13):
for data in self.monthdays2calendar(year,month):
for element in data:
if element[0] != 0 and element[1] == weekday:
counter +=1
return counter
mc = MyCalendar()
print(mc.count_weekday_in_year(2019,0)) #52
print(mc.count_weekday_in_year(2000,6)) #53