
简介针对Python开发中根据日期获取星期几的常见需求这份资料给出了一套直观且有效的解决方案尤其适合需要处理日期标记、定时任务或数据统计场景的Python初学者和有一定基础的中级开发者。资源以PDF文档形式整理共1个文件压缩后仅27KB轻量便携方便随时查阅。内容围绕datetime模块的weekday()方法展开通过定义get_week_day()函数和数字到星期名称的字典映射将0-6的返回值准确转换为“星期一”至“星期天”同时演示了结合datetime.datetime.now()获取当天星期的方法代码段可直接复制到项目中使用。资料还介绍了timetuple()、strftime()、strptime()等常用日期时间函数让读者在解决星期判断之外也能进一步理解Python日期格式化、字符串解析和元组转换的基本思路。目前已有5936人学习下载对于希望快速掌握日期星期转换技巧的开发者而言是一份简明实用的参考。1. 同样是“星期几”为什么有人拿到 0有人拿到 7一个自动发周报的脚本连续三周都没在周五触发查日志发现条件写的是dt.weekday() 5。排查到最后才醒悟Python 的datetime.weekday()里周一才是 0周五对应的是 4周日是 6而另一边接手的数据表里“1”却代表周一。同一个“返回星期几”的需求放在不同模块里居然有完全相反的编号规则。这篇文章要把 Python 根据日期返回星期几的方法完整拆开标准库里到底有哪几种语义、格式化输出怎么用、中文星期怎么拿、时区和跨周怎么处理以及最容易让人翻车的几个坑。适合写定时任务、报表脚本、日历提醒和数据处理逻辑的开发者照着选一个入口函数就能统一全项目。2. 先分清两种星期语义weekday()返回 0isoweekday()返回 12.1weekday()0 代表周一适合做偏移运算Python 内置的date和datetime对象都有一个weekday()方法返回范围是 0 到 60 对应周一6 对应周日。这个编号规则来自 Python 内部对一周的默认切分把周一当作一周的第一天所以周一才是基准点。from datetime import date d date(2025, 7, 1) # 一个普通的星期二 print(d.weekday()) # 输出 1因为周一0周二1weekday()最大的价值在于偏移计算。因为周一是 0那么从任意一天往后退到本周一只需要today - timedelta(daystoday.weekday())而不用去判断今天到底是星期几再手工分类。这种以周一为原点的设计让“取本周日期区间”“按周分组”这类逻辑写起来特别顺。缺点是直觉上容易出错。很多人第一反应以为 1 是周一、7 是周日看到weekday()返回 5 就以为是周五实际上 5 是周六。拿到返回值后先想清楚自己的业务里一周从哪天开始再决定用哪个方法不然代码在逻辑上根本跑不通。2.2isoweekday()17 的返回值适合布尔判断isoweekday()对应 ISO 8601 标准返回 1 到 71 是周一7 是周日。这个语义和人日常认知更接近尤其在判断周末时非常直观from datetime import date d date(2025, 7, 1) print(d.isoweekday()) # 输出 2周二 # 判断是不是周末周六6周日7 is_weekend d.isoweekday() 5isoweekday()的返回值天然适合做边界判断。判断工作日可以直接写 5判断周末直接写 5不需要在代码里反复念叨“周六是 5 还是 6”。如果一段代码需要频繁判断“今天是周几、是不是周末”我会优先用isoweekday()而不是weekday()。需要留神的是两种结果混用同一份代码里前面用weekday()拿偏移后面用isoweekday()拿周几两个数差 1非常容易在比较运算里出问题。规范做法是在公共工具函数里统一出口谁调用都不需要再关心底层用的是哪一种。2.3 参数怎么选手写一个语义可控的获取函数既然两种语义各有用处不如直接封装一个函数把周一为 0、周一为 1、中文名称三种模式都收进去。新代码只调用这一个入口旧代码即使传错了语义也能在一个地方统一修正。from datetime import date, datetime def get_weekday(value, modezero): 根据日期返回星期信息。 value: 支持 date 或 datetime 对象 mode: zero 返回周一0; one 返回周一1; name 返回中文名 if isinstance(value, datetime): value value.date() weekday_index value.weekday() # 0周一, 6周日 if mode zero: return weekday_index if mode one: return weekday_index 1 if mode name: names [星期一, 星期二, 星期三, 星期四, 星期五, 星期六, 星期日] return names[weekday_index] raise ValueError(mode 仅支持 zero / one / name)这个封装把底层差异收敛到了函数内部。参数mode决定返回值基准默认zero保持和weekday()一致避免改了模式后旧逻辑全部失效。返回中文名时用的是固定列表映射不依赖系统语言环境也不会因为服务器 locale 没装中文就输出英文。团队协作时我会把这个函数放到公共模块里并且约定所有涉及星期的判断只准调它不准再直接dt.weekday()。3. strftime 格式化星期%A 的本地化坑与中文映射方案3.1%w、%A、%a各自的语义与易混点strftime()能直接把日期格式化成字符串其中和星期相关的格式符有%w、%A、%a和%u。很多人在这一步开始乱因为%w的取值基准和weekday()不一样。from datetime import date d date(2025, 7, 1) # 周二 print(d.strftime(%w)) # 输出 2注意这里 0 代表周日 print(d.strftime(%A)) # 输出 Tuesday完整英文星期名 print(d.strftime(%a)) # 输出 Tue英文缩写 print(d.strftime(%u)) # 输出 21周一与 isoweekday 一致%w里 0 对应周日1 到 6 对应周一到周六这是从 C 库继承来的习惯和weekday()的“周一0”不一致。%A返回完整英文名%a返回缩写这两个适合直接拼接进日志或报表文件名。%u是 ISO 标准下的星期数字1 到 7但它在部分老系统或 Windows 下的可用性需要实测不能默认一定支持。最安全的做法是需要星期数字做逻辑判断时不要用strftime()直接上weekday()或isoweekday()strftime()只用来做展示和拼接。3.2 中文星期输出不要依赖 locale用手写映射不少人想在文件后缀里带上“星期二”三个字第一反应是设置locale.setlocale()然后用%A。这个方案在本地开发机可能成功了部署到服务器就立刻失效——服务器很可能没有安装中文语言包setlocale直接抛异常或者%A静默退回英文。import locale from datetime import date # 以下代码在缺少中文语言包的服务器上会抛异常或不生效 locale.setlocale(locale.LC_TIME, zh_CN.UTF-8) print(date(2025, 7, 1).strftime(%A)) # 不可靠我一般不会把业务逻辑押在系统 locale 上。更稳的方案是维护一张星期的中文映射表用weekday()的索引去查表无论部署到哪个环境输出都一致。from datetime import date CN_WEEKDAYS [星期一, 星期二, 星期三, 星期四, 星期五, 星期六, 星期日] def chinese_weekday(value): 输入 date/datetime返回中文星期名。 d value.date() if isinstance(value, datetime) else value return CN_WEEKDAYS[d.weekday()] print(chinese_weekday(date(2025, 7, 1))) # 星期二这种写法的好处是零依赖任何装了 Python 解释器的机器行为完全一致。列表顺序严格按weekday()的返回值排列不能随意调整否则索引对应关系就错位了。3.3 完整的中文日期处理函数实际业务里往往既要“星期几”又想要“YYYY年MM月DD日 星期X”这种完整形态。直接基于上一节的映射表再加上原始日期格式化就能拿到报表和告警信息里常见的时间戳文案。from datetime import datetime def format_chinese_datetime(value): 返回 2025年07月01日 星期二 风格的字符串。 if isinstance(value, datetime): d value else: d datetime(value.year, value.month, value.day) date_part d.strftime(%Y年%m月%d日) week_part CN_WEEKDAYS[d.weekday()] return f{date_part} {week_part} print(format_chinese_datetime(date(2025, 7, 1)))这个函数把日期格式化往两个方向拆原始年月日交给strftime星期的中文名走映射表。这样即使在英文环境部署strftime(%Y年%m月%d日)也只是输出数字不受语言包影响。函数入参兼容date和datetime两种类型避免上层调用方还要先统一对象类型。4. 三种实际场景的星期计算字符串入参、时区跨日、本周五定位4.1 从字符串解析日期strptime 的格式与异常处理定时任务里经常从配置文件、数据库字段读到一个字符串日期例如2025-07-01需要先转成日期对象再拿星期。标准做法是strptime指定格式解析然后交给weekday()或isoweekday()。from datetime import datetime raw_date 2025-07-01 try: d datetime.strptime(raw_date, %Y-%m-%d) except ValueError as exc: print(f日期格式无法解析: {exc}) raise print(d.weekday()) # 1说明是周二strptime的格式串必须和输入字符串完全匹配。如果数据里混入了2025/7/1这种斜杠写法上面的代码会抛ValueError。我一般会在解析前做一次简单的清洗把分隔符统一成横杠再走同一套解析逻辑cleaned raw_date.strip().replace(/, -) d datetime.strptime(cleaned, %Y-%m-%d)另外strptime解析字符串时无法自动识别2025-7-1这种不补零的写法格式串里写%m和%d也只会接受两位数字。如果数据源格式不可控更省事的做法是用dateutil.parser.parse这类宽松解析库但引入外部依赖前要把成本算清楚标准库场景下先清洗再做严格解析通常够用。4.2 时区跨日UTC 还是本地时间先转时区再取星期时区问题是最隐蔽的坑。很多服务端代码习惯用datetime.utcnow()取当前时间然后再调weekday()。在 UTC 时区下午 16 点之后东八区已经是次日凌晨两个时区跨了日星期几完全可能不一样。from datetime import datetime, timezone from zoneinfo import ZoneInfo # 错误示范直接用 UTC 时间判断星期 utc_now datetime.now(timezone.utc) print(utc_now.weekday()) # 可能比本地时间少一天 # 正确做法先转换到业务所在时区 local_now utc_now.astimezone(ZoneInfo(Asia/Shanghai)) print(local_now.weekday()) # 这才是本地日历上的星期几业务上说的“今天发周报”指的是用户所在时区的“今天”而不是服务器 UTC 时间的“今天”。所以拿到 UTC 时间后第一步是astimezone()转到目标时区再取日期、再取星期。zoneinfo是 Python 3.9 起标准库自带的时区模块不需要额外装第三方库如果运行在 Windows 且系统没有时区数据则需要补装对应的时区数据包否则ZoneInfo构造会报错。跨时区系统里我会把所有时间统一存 UTC取用时显式转本地时区星期判断只发生在转完时区之后。4.3 定位本周的周五先回周一再正向偏移不少报表逻辑要算“这个周五是哪天”比如本周的周报截止时间。有人会写成“如果今天是周五就取今天否则找最近的周五”这种分支判断在周末时会算错——周六很可能被找成昨天的周五。稳的做法是先回到本周一再往前加偏移天数。from datetime import date, timedelta today date.today() monday today - timedelta(daystoday.weekday()) friday monday timedelta(days4) print(本周一:, monday) print(本周五:, friday)这里利用了weekday()周一为 0 的语义today.weekday()就是今天距离本周一的天数减掉后必然落到周一。拿周一的日期后加上任何偏移都不会跨周出错。同样的方法还能算本周日、上周五、下周二的日期只需要调整偏移量。这种写法把“星期”和“日期”彻底解耦不管今天是周几计算结果都稳定落在当前周内。5. 避开 5 个常见陷阱从周一等于 0 到 UTC 跨日5.1 周一返回 0判断条件写成了weekday() 1现象定时脚本每天执行判断“今天是周一才运行”用dt.weekday() 1判断结果周二运行了周一反而一直没跑。原因weekday()里 0 才是周一1 是周二条件把周一漏掉、把周二命中。解决用dt.isoweekday() 1判断周一语义和人一致或者沿用weekday()但写成dt.weekday() 0。我习惯在代码里加一行注释标明基准防止下次维护的人再踩一次。5.2 服务器没有中文 locale%A输出变成 Friday现象本地运行输出“星期五”部署到 Linux 服务器后变成“Friday”不算报错但自动生成的报表文件名完全不符合预期。原因strftime(%A)的输出语言由系统 locale 决定服务器没安装中文语言包时直接退回英文。解决不要依赖setlocale改用固定中文映射表见 3.2 节的CN_WEEKDAYS方案。这条规则对所有展示型文案都适用宁可代码里多写几个列表也不要赌运行环境的语言包。5.3 UTC 时间判断星期跨日后差一天现象某个推送任务在某些天不触发排查发现代码是datetime.utcnow().weekday() 4而群里用户反馈已经到周五了服务端还按周四算。原因UTC 比东八区慢 8 小时UTC 周四晚上对应东八区周五凌晨两个星期数不同。解决先用astimezone()转到业务所在时区再取weekday()标准写法见 4.2 节。所有面向用户的定时逻辑都应该按用户时区判断而不是按服务器时区。5.4%W与%w混用周数和星期几对不上现象代码里用strftime(%W)算“一年第几周”又用strftime(%w)判断星期几组合出来的结果比手算差一天。原因%W表示一年中的周数以周一作为一周起点%U以周日作为一周起点而%w里周日又对应 0。三个格式符的基准互相不一样混用时逻辑自然对不上。解决需要同时拿“第几周”和“星期几”时改用isocalendar()一次性获取 ISO 年、ISO 周数、ISO 星期几返回值按同一套标准对齐不会出现基准漂移。from datetime import date d date(2025, 7, 1) iso_year, iso_week, iso_weekday d.isocalendar() print(iso_year, iso_week, iso_weekday) # 例如 2025, 27, 25.5 早年日期解析失败strptime不是万能的现象处理历史数据时遇到1899-12-31这样的日期strptime在 Windows 上直接抛ValueError在一些精简的 Linux 容器里也可能行为异常。原因strptime底层依赖 C 库的日期解析Windows 的 C 运行时对 1900 年以前日期支持有限。解决不要用strptime解析早年日期改用date(1899, 12, 31)直接构造日期对象再调weekday()。Python 的date类型本身支持 1 到 9999 年构造方式不受 C 库限制历史数据场景里优先走这条路。6. 进阶把日期转星期封装成工具箱并对比三种实现的性能6.1 一个可复用的“星期工具箱”函数真实项目里日期来源五花八门有的模块传date有的传datetime有的从接口拿字符串还有的给 Unix 时间戳。与其在业务代码里到处写转换逻辑不如做一个统一入口收下各种输入、按需输出不同格式的星期结果。from datetime import datetime, date CN_WEEKDAYS [星期一, 星期二, 星期三, 星期四, 星期五, 星期六, 星期日] def weekday_any(value, outputcn): 统一入口支持多种日期输入返回不同星期格式。 value: date / datetime / YYYY-MM-DD 字符串 / Unix 时间戳 output: cn中文名, iso1~7, zero0~6 if isinstance(value, datetime): d value.date() elif isinstance(value, date): d value elif isinstance(value, str): d datetime.strptime(value.strip(), %Y-%m-%d).date() elif isinstance(value, (int, float)): d datetime.fromtimestamp(value).date() else: raise TypeError(f不支持的日期类型: {type(value).__name__}) weekday_index d.weekday() if output cn: return CN_WEEKDAYS[weekday_index] if output iso: return weekday_index 1 if output zero: return weekday_index raise ValueError(output 仅支持 cn / iso / zero)函数把类型判断收敛在开头转换逻辑集中业务侧不需要知道底层是weekday()还是isoweekday()。参数output控制返回格式cn用于展示iso用于布尔判断zero用于和旧逻辑兼容。字符串统一按YYYY-MM-DD解析并先去除首尾空白时间戳按本地时区转日期注意这点和 4.2 节的时区提醒一致。6.2 三种实现的性能对比与适用边界基准不同决定适用场景不同。这里对比三种常见实现的相对表现单位不写死具体耗时因为不同机器差异大。实现方式相对耗时适用场景datetime.weekday()最快单日期判断、常规业务逻辑calendar.weekday()约慢 1.5 到 2 倍已经有 year/month/day 参数、不想构造日期对象时手写佐木算法接近datetime但纯整数运算批量估算、脱离 datetime 环境的场景from calendar import weekday as cal_weekday from datetime import date # 批量计算 10 万个日期的星期 dates [date(2025, 3, 1 i) if i 28 else date(2025, 4, i - 27) for i in range(100000)] # 方式一datetime.weekday() count 0 for d in dates: count d.weekday() # 方式二calendar.weekday() count2 0 for d in dates: count2 cal_weekday(d.year, d.month, d.day) # 方式三手写佐木算法返回 0周日 def sakamoto(y, m, d): t [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4] if m 3: y - 1 return (y y // 4 - y // 100 y // 400 t[m - 1] d) % 7佐木算法是纯整数运算不依赖日期对象适合在大批量数据处理时避免创建大量 Python 对象。但它返回值以周日为 0和weekday()基准不一致接进业务层前要做一次映射。日常脚本没有性能瓶颈时我不建议手写算法维护成本高于收益只有在先跑过cProfile、确认星期计算确实占热点时才值得换算法。之前做某个跨平台系统时各模块各用各的星期语义周一和周日各差一天最后统一成一个入口函数才彻底根治了问题。希望你现在的项目也能从一开始就定好这个规矩少走一次弯路。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。