蓝桥杯专项突破:Python datetime模块(附6道真题实战演练),彻底拿下日期类问题!
蓝桥杯专项突破:Python datetime模块(附6道真题实战演练),彻底拿下日期类问题!
博主前言:
大家好!在蓝桥杯等算法竞赛中,“日期和时间的推算”几乎是必考的常客。很多同学遇到这类题目,第一反应就是去手写判断平闰年、细扣每个月天数的逻辑。但这不仅代码量大,而且极易在边界条件上踩坑报错。但如果你使用的是 Python,那么恭喜你,你拥有一个官方的超级“外挂” —— 内置的
datetime模块!本篇文章将带你从零开始,系统性地攻克蓝桥杯中的日期计算问题。无论你是刚接触 Python 的萌新,还是准备考前突击的选手,本文都能帮到你。我们将从最基础的模块导入姿势讲起,深度拆解
datetime的核心用法,并硬核剖析 6 道蓝桥杯真题。废话不多说,让我们掌握这些“骗分/拿分”神技,直接开始吧!🚀
1.前提提要-python模块的使用方法(参考:Python3 模块 | 菜鸟教程)
1.1 模块的作用:
- 代码复用:将常用的功能封装到模块中,可以在多个程序中重复使用。
- 命名空间管理:模块可以避免命名冲突,不同模块中的同名函数或变量不会互相干扰。
- 代码组织:将代码按功能划分到不同的模块中,使程序结构更清晰。
1.2 常用语句
1.2.1 import 模块名
用法说明: 这是最基础也是最安全的导入方式。它会将整个指定的模块引入到当前的程序中,但不会直接把模块内部的名字(函数名、类名等)暴露到你当前的代码环境中。
在程序中的调用方法: 由于模块内部的内容没有直接暴露,当你要使用该模块里的类、函数或变量时,必须使用“模块名.”作为前缀来进行访问。这就像是明确告诉 Python:“请去这个特定的模块里,寻找并使用这个功能”。
- 调用函数格式:
模块名.函数名() - 调用类格式:
模块名.类名() - 调用变量格式:
模块名.变量名
具体代码示例:
示例 1:使用 math 模块(数学计算)
import math # 导入整个 math 模块
# 1. 使用 math 模块中的变量 (圆周率 pi)
print(math.pi) # 输出: 3.141592653589793
# 2. 使用 math 模块中的函数 (计算平方根 sqrt)
result = math.sqrt(16)
print(result) # 输出: 4.0
示例 2:使用你提到的 datetime 模块(日期和时间处理)
import datetime # 导入整个 datetime 模块
# 1. 使用 datetime 模块中的 datetime 类,并调用它的 now() 方法获取当前系统时间
current_time = datetime.datetime.now()
print("当前时间是:", current_time)
# 2. 使用 datetime 模块中的 date 类来创建一个具体的日期对象
new_year = datetime.date(2024, 1, 1)
print("元旦是:", new_year)
💡 补充小贴士:起别名 (import ... as ...) 很多时候模块的名字比较长(比如 datetime),每次调用都要写一遍前缀会有些繁琐。这时可以在导入时使用 as 关键字给模块起个简短的“别名”:
import datetime as dt # 将 datetime 模块导入,并简写为 dt
# 之后的代码中,直接用 dt 代替 datetime
current_time = dt.datetime.now()
1.2.2 from 模块名 import *
用法说明:
这种导入方式会将目标模块中所有公开的类、函数和变量一次性全部“倒”进你当前的代码环境中。这里的星号 * 代表“全部”(通配符)。
在程序中的调用方法:
因为模块里的所有内容都已经直接暴露在当前环境里了,所以你完全不需要再加“模块名.”的前缀,直接写函数名、类名或变量名就可以使用。
- 调用函数格式:
函数名() - 调用类格式:
类名() - 调用变量格式:
变量名
具体代码示例:
示例:使用 math 模块
from math import * # 导入 math 模块里的所有公开内容
# 1. 直接使用变量 pi,不需要写 math.pi
print(pi) # 输出: 3.141592653589793
# 2. 直接使用函数 sqrt,不需要写 math.sqrt
result = sqrt(16)
print(result) # 输出: 4.0
💡 核心警告(进阶知识):慎用 import \*
虽然 from 模块名 import * 看起来非常方便,能让你在写代码时少打很多次前缀,但在实际的工程开发中,这是一种极其不推荐的写法。原因如下:
- 命名空间污染与冲突: 假设你写了一个函数叫
log()(用来记录日志),然后你又写了from math import *。因为math模块里恰好也有一个算对数的函数叫log(),它就会把你原来写的log()覆盖掉,导致程序出现莫名其妙的错误,且极难排查。 - 可读性极差: 当你的代码达到几百行时,突然出现一个独立的函数调用(比如
do_something()),其他看你代码的人(或者几个月后的你自己)完全不知道这个函数是你自己写的,还是从哪个第三方模块里导入的。
更好的替代方案:按需导入
如果你确实不想写长长的前缀,但又想保持代码安全,推荐明确指定你要导入什么:
# 只导入自己需要的特定函数或变量
from math import pi, sqrt
print(pi)
print(sqrt(25))
这样既享受了简写的便利,又清楚地交代了这些功能的来源。
太棒了,这部分是日常写代码中最常用、也是最推荐的导入方式。你可以把下面的内容无缝衔接到你的笔记中:
1.2.3 from 模块名 import 成员名1, 成员名2…
用法说明:
这是实际开发中最推荐的“按需导入”方式。它只会把你明确指定的函数、类或变量从目标模块中提取出来,放入当前的代码环境中。这种做法既不会引入多余的代码(节省资源),又能精准控制命名空间,避免像 import * 那样产生不可预知的名字冲突。
在程序中的调用方法:
因为你指定的特定成员已经被直接引入了当前环境,所以完全不需要加“模块名.”的前缀,直接使用即可。
- 调用函数格式:
函数名() - 调用类格式:
类名() - 调用变量格式:
变量名
具体代码示例:
示例 1:使用 math 模块(导入特定变量和函数)
# 仅仅从 math 模块中挑选 pi (变量) 和 sqrt (函数) 导入
from math import pi, sqrt
# 直接使用,不需要写 math.pi 或 math.sqrt
print(pi) # 输出: 3.141592653589793
print(sqrt(25)) # 输出: 5.0
示例 2:使用 datetime 模块(导入特定的类)
注意:这里很容易混淆,模块名叫 datetime,里面也有一个类叫 datetime。
# 从 datetime 模块中,仅仅导入 datetime 这个类
from datetime import datetime
# 直接调用被导入的 datetime 类的 now() 方法
current_time = datetime.now()
print("当前时间是:", current_time)
💡 补充小贴士:给特定的成员起别名 (as)
就像给整个模块起别名一样,当你从模块中 import 特定的函数或类时,也可以使用 as 关键字给它换个名字。这在避免命名冲突时极其有用:
# 假设你当前的代码里已经自己写了一个叫 sqrt 的函数
# 为了防止 math 里的 sqrt 把你写的覆盖掉,可以给导入的函数改个名
from math import sqrt as math_sqrt
# 调用时使用新名字
result = math_sqrt(9)
print(result) # 输出: 3.0
2.datetime模块介绍
Python 的 datetime 模块是用于处理日期和时间的标准库模块。它提供了多种类和函数,可以帮助我们轻松地处理日期、时间、时间差等操作。无论是获取当前时间、格式化日期,还是计算时间差,datetime 模块都能胜任。
datetime 模块的核心类
datetime 模块中包含了以下几个核心类:
date类 -date类用于表示日期,包含年、月、日三个属性。time类 -time类用于表示时间,包含时、分、秒、微秒等属性。datetime类 -datetime类是date和time的结合体,可以同时表示日期和时间。timedelta类 -timedelta类用于表示时间差,可以用于日期和时间的加减操作。
很高兴继续帮你完善笔记!datetime 是 Python 中处理日期和时间最核心、也最实用的标准库。
结合你刚才学习的 from ... import ... 语法,我为你整理了一份结构清晰的 datetime 模块教程。你可以直接将这篇内容作为你的**“日期时间处理”**专题笔记。
1. datetime 模块核心类概览
datetime 模块中包含了好几个不同的“类”,专门用来处理不同维度的的时间数据。以下是菜鸟教程中最常提及的核心类:
| 类名 | 描述 | 常用场景 |
|---|---|---|
datetime.date |
仅表示日期(年、月、日) | 生日、账单日、纪念日等不需要具体到几点几分的场景。 |
datetime.time |
仅表示时间(时、分、秒、微秒) | 闹钟时间、每天的营业时段等不需要绑定具体日期的场景。 |
datetime.datetime |
表示日期和时间(年、月、日、时、分、秒) | 最常用。日志记录、文章发布时间、获取系统当前时间等。 |
datetime.timedelta |
表示时间间隔(天、秒、微秒) | 时间的加减运算,比如计算两个日期的差值(倒计时、会员过期计算)。 |
2. 常用操作与代码实例
在实际开发中,我们通常会使用“按需导入”的方式来使用这些类。
2.1 获取当前日期和时间
最基础的操作,获取系统当下的时间。
from datetime import datetime, date
# 获取当前完整的日期和时间 (包含年月日时分秒)
now = datetime.now()
print(f"当前系统时间: {now}")
# 仅获取今天的日期 (不包含时分秒)
today = date.today()
print(f"今天的日期是: {today}")
2.2 构造指定的日期和时间
除了获取当前时间,我们经常需要手动创建一个特定的时间对象。
from datetime import datetime, date, time
# 构造指定日期:2024年10月1日 (参数顺序:年, 月, 日)
national_day = date(2024, 10, 1)
# 构造指定时间:晚上 8点30分 (参数顺序:时, 分, 秒)
evening_time = time(20, 30, 0)
# 构造指定日期和时间:2024年1月1日 凌晨0点0分
new_year = datetime(2024, 1, 1, 0, 0, 0)
# 可以单独提取对象的属性
print(f"元旦的年份是: {new_year.year}")
print(f"元旦的月份是: {new_year.month}")
2.3 日期时间的格式化与解析(⭐ 重点!)
这是工作中最常用的功能:把程序里的时间对象变成用户看得懂的漂亮字符串,或者把用户输入的字符串转换成程序能处理的时间对象。
你需要记住两个核心方法:
strftime()(Format): 将时间对象 → \rightarrow → 转换为字符串 (String Format Time)strptime()(Parse): 将字符串 → \rightarrow → 解析为时间对象 (String Parse Time)
常用的格式化符号表:
| 格式符 | 说明 | 示例 |
|---|---|---|
%Y |
4位数的年份 | 2024 |
%m |
2位数的月份 (01-12) | 09 |
%d |
2位数的日期 (01-31) | 05 |
%H |
24小时制的小时 (00-23) | 14 |
%M |
2位数的分钟 (00-59) | 30 |
%S |
2位数的秒 (00-59) | 59 |
代码示例:
from datetime import datetime
now = datetime.now()
# 1. strftime: 格式化输出 (把时间变成自定义的字符串格式)
# 例如我们要输出:YYYY-MM-DD HH:MM:SS
formatted_str = now.strftime("%Y-%m-%d %H:%M:%S")
print(f"格式化输出: {formatted_str}")
# 还可以换成中文格式
chinese_format = now.strftime("%Y年%m月%d日")
print(f"中文格式: {chinese_format}")
# 2. strptime: 解析字符串 (把字符串变回 datetime 对象)
# 假设我们从数据库或前端拿到了一个字符串格式的时间
date_string = "2023-12-25 18:00:00"
# 第二个参数必须与字符串的格式完全匹配!
parsed_date = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
print(f"解析成功,对象的类型是: {type(parsed_date)}")
2.4 时间的加减计算 (timedelta)
如果你想计算“3天后是几号”或者“距离活动结束还有多久”,就需要用到 timedelta。
Python
from datetime import datetime, timedelta
now = datetime.now()
# 构造一个 7 天的时间间隔
seven_days = timedelta(days=7)
# 计算 7 天后的时间 (直接用加号)
future_date = now + seven_days
print(f"7天后是: {future_date}")
# 计算 3 小时前的时间 (直接用减号)
three_hours_ago = now - timedelta(hours=3)
print(f"3小时前是: {three_hours_ago}")
# 计算两个日期之间的差值
date1 = datetime(2024, 5, 1)
date2 = datetime(2024, 5, 10)
diff = date2 - date1
print(f"这两个日期相差了 {diff.days} 天")
没问题!将实战题目加入笔记是非常好的学习方法,这样不仅能看到理论,还能知道在真正的算法竞赛(如蓝桥杯)中是如何应用这些知识的。
我为你整理了一个新的小节**“3. 蓝桥杯实战演练(datetime 模块综合应用)”**,并为你提供的 6 段代码添加了核心考点解析和注释,帮你更好地复习。你可以直接将以下内容复制并接在你的笔记最后:
3. 蓝桥杯实战演练(datetime 模块综合应用)
在蓝桥杯等算法竞赛中,遇到日期、时间推算的问题,直接使用 datetime 模块不仅能大幅减少代码量,还能避免自己手写“平/闰年判断”、“每月天数判断”带来的逻辑错误。以下是几个常见的实战题型及解法。
实战案例 1:计算某一天是这一年的第几天
核心考点: 构造 date 对象、使用日期相减得到 timedelta 对象、提取 .days 属性。
代码实现:
import os
import sys
from datetime import *
a = []
# 持续接收输入,直到输入 0 0 0 为止
while True:
y, m, d = map(int, input().split())
if y == 0 and m == 0 and d == 0:
break
# 构造当前日期对象
date_current = date(y, m, d)
# 构造该年 1 月 1 日的基准日期对象
date_initial = date(y, 1, 1)
# 两个 date 对象相减会得到一个 timedelta 对象,提取其 days 属性并加 1
a.append((date_current - date_initial).days + 1)
for i in a:
print(i)
实战案例 2:2022年跑步打卡天数统计
题目要求: 每周六、日跑步,每月 1、11、21、31 号跑步,2022年一共跑几次?
核心考点: 日期遍历逻辑、使用 weekday() 方法判断星期几(注意:周一返回 0,周日返回 6)。
代码实现:
from datetime import *
result = 0
# 遍历 1 到 12 月
for month in range(1, 13):
# 自己判断每月的天数
if month in [1, 3, 5, 7, 8, 10, 12]:
day = 31
elif month in [4, 6, 9, 11]:
day = 30
else:
day = 28 # 2022年是平年,2月有28天
for d in range(1, day + 1):
date_current = date(2022, month, d)
# weekday() 返回 5 代表周六,6 代表周日
if date_current.weekday() in [5, 6] or d in [1, 11, 21, 31]:
result += 1
print(result)
实战案例 3:统计特定星期几的特定日期
题目要求: 统计 1901 年到 2000 年(100年间),有多少个月的 1 号是星期日?
核心考点: 嵌套循环遍历年份和月份,结合 weekday() == 6 判断周日。
代码实现:
import os
import sys
from datetime import *
result = 0
for year in range(0, 100):
for month in range(1, 13):
# 直接构造每年的每月 1 号
date_current = date(1901 + year, month, 1)
# 星期日对应的数字是 6
if date_current.weekday() == 6:
result += 1
print(result)
实战案例 4:2023年跑步公里数综合计算
题目要求: 按照特定规则(周一或日期数字中包含 ‘1’ 跑 5 公里,否则跑 1 公里)计算 2023 年总公里数。
核心考点: weekday() 判断、对象属性提取(month, day)及类型转换匹配。
代码实现:
import os
import sys
from datetime import *
run = 0
for month in range(1, 13):
if month in [1, 3, 5, 7, 8, 10, 12]:
day = 31
elif month in [4, 6, 9, 11]:
day = 30
else:
day = 28 # 2023年平年
for d in range(1, day + 1):
current_date = date(2023, month, d)
# 判断:1. 是周一(weekday==0);2. 月份包含'1';3. 日期包含'1'
if current_date.weekday() == 0 or '1' in str(current_date.month) or '1' in str(current_date.day):
run += 5
else:
run += 1
print(run)
实战案例 5:按天数步进遍历日期区间
题目要求: 统计某年内,满足特定月份和日期要求的总天数权重(类似于 Cron 表达式匹配)。
核心考点: 不再使用 for 循环嵌套,而是使用 while 循环配合 timedelta(days=1) 进行日期递增。这是遍历日期区间最安全的写法,不用管每个月多少天。
代码实现:
import os
import sys
from datetime import *
# (省略输入解析部分的逻辑,重点关注日期处理)
result = 0
date_1 = input().split()
a = [[0,59], [0,59], [0,23], [1,31], [1,12]]
for i in range(5):
if '*' in date_1[i]:
date_1[i] = range(a[i][0], a[i][1]+1)
elif ',' in date_1[i]:
date_1[i] = [int(x) for x in date_1[i].split(',')]
elif '-' in date_1[i]:
date_1[i] = range(int(date_1[i].split('-')[0]), int(date_1[i].split('-')[1])+1)
else:
date_1[i] = [int(date_1[i])]
s, f, h, d, m = date_1
day_mask = len(s) * len(f) * len(h)
cnt = 0
# 构造步长为 1 天的 timedelta 对象
t = timedelta(days=1)
start = date(2023, 1, 1)
end = date(2024, 1, 1)
# 使用 while 循环遍历每一天
while start < end:
if start.month in m and start.day in d:
cnt += day_mask
# 核心:日期对象直接加上 1 天
start += t
print(cnt)
实战案例 6:时间字符串解析、计算与反向格式化
题目要求: 给定一个时间字符串和分钟数 x x x,计算自 1970年1月1日以来,时间过去了多少个完整的 x x x 分钟,并输出那个基准时刻的格式化字符串。
核心考点: strptime()(字符串转时间)、strftime()(时间转字符串)、timedelta 之间的整除运算(//)。
代码实现:
from datetime import *
result = []
T = int(input())
# 设定基准时间
start_date = datetime(1970, 1, 1, 0, 0, 0)
for i in range(T):
strings = input().split()
# 1. strptime: 把输入的字符串解析成 datetime 对象
current_date = datetime.strptime(strings[0] + strings[1], "%Y-%m-%d%H:%M:%S")
x = int(strings[2])
# 2. timedelta 运算: 计算与基准时间的差值
delta_time = current_date - start_date
# 3. 两个 timedelta 对象可以进行整除,计算出经历了多少个完整的 x 分钟段
n = delta_time // timedelta(minutes=x)
# 4. strftime: 重新计算基准点并格式化为字符串
result_str = (start_date + n * timedelta(minutes=x)).strftime("%Y-%m-%d %H:%M:%S")
result.append(result_str)
for i in range(T):
print(result[i])
💡 总结蓝桥杯解题思路:
- 遇到**“相差多少天”*、*“加上多少天后是哪天”**的问题,优先使用
date对象 +timedelta加减运算。 - 遇到**“遍历某一年所有的日期”**,既可以用
for循环嵌套枚举月和日,也可以设置一个起点date,然后在一个while循环里不断+ timedelta(days=1)(后者不容易在天数判断上出错)。 - 遇到**“求星期几”**,坚决不要自己写公式推算,直接用
date.weekday()!
🎯 写在最后
日期时间类问题在蓝桥杯中绝对属于**“必拿分”**的基础题型。只要我们熟练掌握了 date、datetime 的对象构造,以及神兵利器 timedelta 的加减推算,那些曾经让人头疼的日历逻辑就会变得迎刃而解。
备考小建议:
大家在看懂代码之后,一定要自己打开 IDE 把这 6 道真题的逻辑亲手敲一遍!“看懂了”和“能闭着眼睛写出来”在考场上是完全不同的两个概念。
💬 互动交流:
如果这篇文章对你的备考有所启发,或者帮你省去了查阅资料的时间,请不要吝啬你的 点赞 👍、收藏 ⭐ 和 关注 ➕!这是对我持续分享干货最大的鼓励。你在蓝桥杯备考或刷题时,还遇到过哪些容易卡壳的日期问题吗?欢迎在评论区留言交流,我们一起探讨解决!
最后,祝愿大家在即将到来的蓝桥杯赛场上:键盘敲烂,Bug 退散,代码一次 AC,顺利拿下理想的奖项! 🏆 我们下篇文章见!
更多推荐



所有评论(0)