蓝桥杯专项突破: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 * 看起来非常方便,能让你在写代码时少打很多次前缀,但在实际的工程开发中,这是一种极其不推荐的写法。原因如下:

  1. 命名空间污染与冲突: 假设你写了一个函数叫 log()(用来记录日志),然后你又写了 from math import *。因为 math 模块里恰好也有一个算对数的函数叫 log(),它就会把你原来写的 log() 覆盖掉,导致程序出现莫名其妙的错误,且极难排查。
  2. 可读性极差: 当你的代码达到几百行时,突然出现一个独立的函数调用(比如 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 类是 datetime 的结合体,可以同时表示日期和时间。
  • 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()

🎯 写在最后

日期时间类问题在蓝桥杯中绝对属于**“必拿分”**的基础题型。只要我们熟练掌握了 datedatetime 的对象构造,以及神兵利器 timedelta 的加减推算,那些曾经让人头疼的日历逻辑就会变得迎刃而解。

备考小建议:
大家在看懂代码之后,一定要自己打开 IDE 把这 6 道真题的逻辑亲手敲一遍!“看懂了”和“能闭着眼睛写出来”在考场上是完全不同的两个概念。

💬 互动交流:
如果这篇文章对你的备考有所启发,或者帮你省去了查阅资料的时间,请不要吝啬你的 点赞 👍、收藏 ⭐ 和 关注 ➕!这是对我持续分享干货最大的鼓励。

你在蓝桥杯备考或刷题时,还遇到过哪些容易卡壳的日期问题吗?欢迎在评论区留言交流,我们一起探讨解决!

最后,祝愿大家在即将到来的蓝桥杯赛场上:键盘敲烂,Bug 退散,代码一次 AC,顺利拿下理想的奖项! 🏆 我们下篇文章见!

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐