Last active
December 30, 2021 03:40
-
-
Save shanehh/ec57cc8bff3ac867923b2f620f1cf637 to your computer and use it in GitHub Desktop.
get weeknum of gregorian
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import datetime as dt | |
from collections import namedtuple | |
SUNDAY = "Sunday" | |
yearweek = namedtuple("yearweek", ["year", "week"]) | |
def get_weekday(date: dt.date) -> str: | |
""" | |
e.g. | |
date(2022, 1, 2).strftime("%A") == "Sunday" | |
""" | |
return date.strftime("%A") | |
def get_last_sunday(year: int) -> dt.date: | |
""" | |
获得一年的最后一个星期天: | |
从最后一天开始数,数到星期天 | |
""" | |
# 获得昨天的日期 | |
yesterday = lambda d: d - dt.timedelta(days=1) | |
last_sunday = dt.date(year, 12, 31) | |
while get_weekday(last_sunday) != SUNDAY: | |
last_sunday = yesterday(last_sunday) | |
return last_sunday | |
def get_weeknum(date: dt.date) -> yearweek: | |
""" | |
e.g. | |
date(2022, 1, 2) == "202202" | |
""" | |
# 先处理年底的特殊 case: | |
# 如果「明年第一天」不是星期天 | |
# 需要判断,是否 | |
# 「今年最后一个星期天」 <= date < 「明年第一天」 | |
# 是,则为明年的第一周 | |
next_y_d1 = dt.date(date.year + 1, 1, 1) | |
if get_weekday(next_y_d1) != SUNDAY: | |
last_sunday = get_last_sunday(date.year) | |
if last_sunday <= date: | |
return yearweek(date.year + 1, 1) | |
# 如果新年的第一天就是星期天的话 | |
# 直接通过天数的差异算 weeknum | |
# 规则是: | |
# 1. 每满 7 天,周数加 1 | |
# 2. 如果有余数,或余数就为 0(本身是 sunady 的情况)也加 1 | |
# 最终数学公式就是:floor division 7, plus 1 | |
day1 = dt.date(date.year, 1, 1) | |
if get_weekday(day1) == SUNDAY: | |
return yearweek(date.year, (date - day1).days // 7 + 1) | |
else: | |
# 否则新年的第一个星期天 | |
# 是「第二周的第一天} | |
tomorrow = lambda d: d + dt.timedelta(days=1) | |
# 寻找「第二周的第一天」 | |
w2d1 = dt.date(date.year, 1, 2) | |
while get_weekday(w2d1) != SUNDAY: | |
w2d1 = tomorrow(w2d1) | |
# 日期小于「第二周的第一天」 | |
# 是第一周 | |
if date < w2d1: | |
return yearweek(date.year, 1) | |
return yearweek(date.year, (date - w2d1).days // 7 + 2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment