以 Python 方式重用你的日历
昨天得到了一个 2016 年的日历。我脑海中浮现出一个有趣的问题:我什么时候可以重用这个日历,哪一年可以重用哪个旧日历?
2015 年 1 月 1 日是星期四。2016 年同一天是星期五。一旦你遵循此模式,你会很快认识到七年的基本周期被闰年打破。
很快发现,对于某些年份,需要几十年才能重用日历:2016 年是闰年,所以你不能在 2044 年重用它。
然而,有一个目前在 whencanireusethiscalendar.com 等在线服务中未实现的巧妙特性:你可以部分重用日历。
两个日历不匹配的原因通常是其中一个有闰日。然而,它们通常在闰日之前或从闰日后一天开始匹配。我们分别称这些年份为部分重用年份 (A) 和 (B)。一旦你考虑此选项(即你在闰日附近交换日历,假设我们有一年的 (A) 和 (B) 可重用日历),你就能重用日历 — 特别是像 2016 年这样的闰年日历。
基于此见解,我编写了一个仅使用核心库的简单暴力 Python 脚本。你可以简单地用要重用日历的年份在命令行调用它:
reuse-calendars.sh
python3 reuse-calendars.py 2015该脚本使用试错方法,因为对于现代计算机来说搜索空间相当小:
reuse-calendars.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
计算你可以重用日历的年份列表。
此脚本计算三种类型的重用年份:
- 完全重用年份,星期几每天都匹配
- 部分重用年份 (A),到闰日(2 月 29 日)为止每天都匹配
- 部分重用年份 (B),从闰日(2 月 29 日)后一天开始每天都匹配
部分重用年份按设计不包括完全重用年份。
"""
__copyright__ = "Copyright (c) 2015 Uli Köhler"
__license__ = "Apache License v2.0"
__version__ = "1.1"
from datetime import date
from collections import namedtuple
ReuseYears = namedtuple('ReuseYears',
['year', 'fullReuseYears',
'partialReuseYearsA', 'partialReuseYearsB'])
def getReuseYears(year, startYear=2005, stopYear=2050):
"""
获取你可以重用日历的年份作为 ReuseYears 对象。
"""
# 获取两个参考日期之一的 ISO 星期几编号
# 参考日期 1 是一年的第一天
# 参考日期 2 是闰日之后的任何日期
refdate1 = lambda y: date(y, 1, 1).isoweekday()
refdate2 = lambda y: date(y, 5, 1).isoweekday()
fullYears = []
partialYearsA = [] # 直到闰日
partialYearsB = [] # 从闰日开始
for otherYear in range(startYear, stopYear + 1):
if otherYear == year: continue
aMatch = refdate1(year) == refdate1(otherYear)
bMatch = refdate2(year) == refdate2(otherYear)
if aMatch and bMatch:
fullYears.append(otherYear)
elif aMatch:
partialYearsA.append(otherYear)
elif bMatch:
partialYearsB.append(otherYear)
return ReuseYears(year, fullYears, partialYearsA, partialYearsB)
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('year', type=int, help='要获取的年份')
args = parser.parse_args()
print(getReuseYears(args.year))Check out similar posts by category:
Algorithms
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow