Skip to content

Instantly share code, notes, and snippets.

@shanehh
Last active December 30, 2021 03:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shanehh/ec57cc8bff3ac867923b2f620f1cf637 to your computer and use it in GitHub Desktop.
Save shanehh/ec57cc8bff3ac867923b2f620f1cf637 to your computer and use it in GitHub Desktop.
get weeknum of gregorian
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