日期时间
本教程共 70 篇 · 第 49 篇 · 更新于 2026-07-22 · 约 6 分钟阅读
49. 日期时间
本节目标:熟练掌握
datetime模块的核心类,学会时间格式化、计算和时区处理。
日期时间是编程里的高频需求:记录日志时间、计算倒计时、处理用户时区、比较两个日期的间隔……Python 的 datetime 模块提供了完整的解决方案。
datetime 模块的核心类
datetime 模块里有五个常用类:
| 类 | 含义 | 示例 |
|---|---|---|
date | 日期(年月日) | 2024-07-21 |
time | 时间(时分秒微秒) | 14:30:00 |
datetime | 日期+时间 | 2024-07-21 14:30:00 |
timedelta | 两个日期/时间的间隔 | 3 days, 2:00:00 |
timezone | 时区信息 | UTC+8 |
获取当前时间
from datetime import datetime, date
now = datetime.now()
print(now) # 2024-07-21 14:30:25.123456
print(now.year) # 2024
print(now.month) # 7
print(now.day) # 21
print(now.hour) # 14
print(now.minute) # 30
print(now.second) # 25
today = date.today()
print(today) # 2024-07-21
Tip
datetime.now()返回本地时间。如果需要 UTC 时间,用datetime.now(timezone.utc)或datetime.utcnow()(后者返回不带时区信息的 UTC 时间,不推荐)。
创建特定时间
from datetime import datetime, date, time
d = date(2024, 7, 21)
t = time(14, 30, 0)
dt = datetime(2024, 7, 21, 14, 30, 0)
print(d) # 2024-07-21
print(t) # 14:30:00
print(dt) # 2024-07-21 14:30:00
Warning月份和日期不能写前导零:
datetime(2024, 07, 21)会报SyntaxError,因为 Python 把07当成八进制数了。正确写法是datetime(2024, 7, 21)。
时间格式化:strftime 和 strptime
strftime:时间对象 → 字符串
from datetime import datetime
now = datetime.now()
print(now.strftime('%Y-%m-%d')) # 2024-07-21
print(now.strftime('%H:%M:%S')) # 14:30:00
print(now.strftime('%Y年%m月%d日 %H:%M')) # 2024年07月21日 14:30
常用格式化符号:
| 符号 | 含义 | 示例 |
|---|---|---|
%Y | 四位年份 | 2024 |
%m | 月份(01-12) | 07 |
%d | 日期(01-31) | 21 |
%H | 小时(00-23) | 14 |
%M | 分钟(00-59) | 30 |
%S | 秒(00-59) | 00 |
%A | 星期几(英文) | Sunday |
%w | 星期几(0-6,0 是周日) | 0 |
strptime:字符串 → 时间对象
from datetime import datetime
dt = datetime.strptime('2024-07-21 14:30:00', '%Y-%m-%d %H:%M:%S')
print(dt) # 2024-07-21 14:30:00
strptime 是 strftime 的逆操作。格式字符串必须和输入字符串严格匹配。
时间计算:timedelta
from datetime import datetime, timedelta
now = datetime.now()
# 加减时间
future = now + timedelta(days=3, hours=2)
past = now - timedelta(weeks=1)
print(future)
print(past)
# 两个时间的差
birthday = datetime(2024, 12, 25)
delta = birthday - now
print(f"距离生日还有 {delta.days} 天")
timedelta 支持的关键字参数:days、seconds、microseconds、milliseconds、minutes、hours、weeks。
Note
timedelta只能精确到天和秒级,不能直接用「月」或「年」。因为月份天数不固定。需要做月份计算时,用dateutil第三方库的relativedelta。
时间戳转换
时间戳(timestamp)是从 1970-01-01 00:00:00 UTC 开始的秒数。数据库和 API 接口里经常用它表示时间。
from datetime import datetime
now = datetime.now()
ts = now.timestamp() # datetime -> 时间戳
print(ts) # 1721545825.123456
dt = datetime.fromtimestamp(ts) # 时间戳 -> 本地 datetime
utc_dt = datetime.utcfromtimestamp(ts) # 时间戳 -> UTC datetime
Warning
fromtimestamp()返回的是本地时间,utcfromtimestamp()返回的是 UTC 时间但没有带时区信息。建议统一使用时区感知对象,避免歧义。
时区处理
Python 3.9+ 的 datetime 内置了 timezone 类,可以创建带时区信息的时间:
from datetime import datetime, timezone, timedelta
# 创建 UTC 时间
utc_now = datetime.now(timezone.utc)
print(utc_now) # 2024-07-21 06:30:00+00:00
# 创建东八区时间
china_tz = timezone(timedelta(hours=8))
beijing_now = datetime.now(china_tz)
print(beijing_now) # 2024-07-21 14:30:00+08:00
# 时区转换
utc = datetime.now(timezone.utc)
local = utc.astimezone(china_tz)
print(local) # 2024-07-21 14:30:00+08:00
Tip如果你的项目涉及时区,推荐安装
pytz或zoneinfo(Python 3.9+ 内置)。它们提供了完整的时区数据库(包括夏令时),比手动写timedelta(hours=8)更准确。from zoneinfo import ZoneInfo dt = datetime.now(ZoneInfo('Asia/Shanghai'))
实战:计算工作日
假设你需要计算两个日期之间有多少个工作日(不含周末):
from datetime import datetime, timedelta
def workdays_between(start: datetime, end: datetime) -> int:
count = 0
current = start
while current <= end:
if current.weekday() < 5: # 0-4 是周一到周五
count += 1
current += timedelta(days=1)
return count
start = datetime(2024, 7, 1)
end = datetime(2024, 7, 21)
print(f"工作日:{workdays_between(start, end)} 天")
Note这个例子没考虑法定节假日。真实业务中,节假日数据需要额外维护。第三方库
workalendar提供了各国的工作日历,可以直接用。
小结
datetime是日期时间的核心类,date和time是它的组成部分。strftime把时间变字符串,strptime把字符串变时间。timedelta做时间加减,支持天、秒、小时等单位。timestamp()和fromtimestamp()做时间戳转换。- 涉及时区时,尽量用带
tzinfo的「感知型」时间对象。
时间处理最烦人的地方是「边界情况」:闰年、夏令时、时区转换、月末最后一天。写日期时间相关的代码时,多测几个特殊日期,能帮你提前发现问题。
来源:参考了 runoob「Python3 日期和时间」、liaoxuefeng「datetime」、pythondoc「datetime 模块」等,改写后所得。