datetime 模块提供了多种操作来表示和操作日期和时间,修改一个 datetime 对象通常有两种方法:

- 使用
replace()方法:创建一个新的datetime对象,并指定你想要修改的年、月、日、时、分、秒等部分,这是最常用和最安全的方法,因为它不会改变原始对象。 - 使用
timedelta对象:用于进行相对时间的计算,比如增加或减少几天、几小时、几分钟等。
使用 replace() 方法
replace() 方法非常适合修改 datetime 对象中的特定部分(只改日期,不改时间),或者创建一个新的对象来表示同一天的某个特定时间。
基本语法
new_datetime = original_datetime.replace(year=YYYY, month=M, day=d, hour=h, minute=m, second=s, microsecond=us)
所有参数都是可选的,如果你不提供某个参数,它会使用原始对象中对应的值。
示例代码
from datetime import datetime
# 1. 创建一个原始的 datetime 对象
dt = datetime(2025, 10, 26, 10, 30, 0)
print(f"原始时间: {dt}")
# 2. 修改年份
new_year = dt.replace(year=2025)
print(f"修改年份后: {new_year}")
# 3. 修改月份和日期
new_month_day = dt.replace(month=11, day=25)
print(f"修改月份和日期后: {new_month_day}")
# 4. 修改时间部分
new_time = dt.replace(hour=15, minute=45)
print(f"修改时间后: {new_time}")
# 5. 同时修改多个部分
new_all = dt.replace(year=2025, month=1, day=1, hour=0, minute=0, second=0)
print(f"修改所有部分后: {new_all}")
# 6. 只修改微秒
# 注意:replace 不会自动进位,比如将秒设为 60 不会变成 1 分钟
new_microsecond = dt.replace(microsecond=500000)
print(f"修改微秒后: {new_microsecond}")
# 7. 关键点:replace() 返回的是新对象,原始对象不变
print(f"检查原始对象是否改变: {dt}") # 原始对象 dt 依然是 2025-10-26 10:30:00
使用 timedelta 对象
timedelta 表示一个时间差或持续时间,你可以用它来将一个 datetime 对象向前或向后移动。
基本语法
from datetime import timedelta # 创建一个时间差对象 delta = timedelta(days=1, hours=2, seconds=30) # 将时间差加到 datetime 对象上 new_datetime = original_datetime + delta # 或者从 datetime 对象上减去时间差 another_new_datetime = original_datetime - delta
timedelta 的常用参数包括:days, seconds, microseconds, milliseconds, minutes, hours, weeks。

示例代码
from datetime import datetime, timedelta
# 创建一个原始的 datetime 对象
dt = datetime(2025, 10, 26, 10, 30, 0)
print(f"原始时间: {dt}")
# 1. 增加 5 天
five_days_later = dt + timedelta(days=5)
print(f"5天后: {five_days_later}")
# 2. 减少 2 小时
two_hours_ago = dt - timedelta(hours=2)
print(f"2小时前: {two_hours_ago}")
# 3. 增加 1 周 3 天 1 小时
complex_delta = timedelta(weeks=1, days=3, hours=1)
complex_later = dt + complex_delta
print(f"1周3天1小时后: {complex_later}")
# 4. 计算两个日期之间的差值
dt2 = datetime(2025, 11, 15)
difference = dt2 - dt
print(f"从 {dt} 到 {dt2} 的差值: {difference}")
print(f"这个差值是 {difference.days} 天")
print(f"这个差值是 {difference.seconds} 秒") # 注意:差值的秒数不包括整天数部分
高级技巧:结合 replace() 和 timedelta
在实际应用中,这两种方法经常结合使用,获取“下个月的第一个周一”。
from datetime import datetime, timedelta
# 假设我们有一个日期
dt = datetime(2025, 10, 26)
# 1. 先使用 replace() 转换到下个月的第一天
first_of_next_month = dt.replace(day=1, month=11) # 2025-11-01
# 2. 然后使用 timedelta 和 weekday() 找到第一个周一
# weekday() 返回的是星期几(周一为0,周日为6)
# 11月1日是星期三 (weekday() == 2)
# 我们需要加上 (7 - 2 + 1) % 7 天?不,更简单的方法是:
# 如果是周三,要找到下一个周一,需要加 5 天 (周一 - 周三 = -2, 7-2=5)
# 或者更通用的方法: (7 - current_weekday + target_weekday) % 7
# 目标是周一 (1),当前是周三 (2)
# (7 - 2 + 1) % 7 = 6 % 7 = 6 天
# 但更直观的逻辑是:
# 如果当前是周一,加0天;周二,加6天;周三,加5天;...;周日,加1天。
# 简单方法:找到下周一
# first_of_next_month.weekday() 是 0 (周一),那它就是我们要的
# 否则,我们要加上 (7 - first_of_next_month.weekday()) 天
# 但我们要的是“第一个”周一,所以如果1号不是周一,就往后找
# (1 - first_of_next_month.weekday() + 7) % 7 这个公式可以算出要加几天
# 但更简单的是:
days_to_add = (0 - first_of_next_month.weekday()) % 7
if days_to_add == 0: # 如果1号就是周一
days_to_add = 0
else:
days_to_add = 7 - first_of_next_month.weekday() # 这个不对,如果1号是周二(1),要加6天到下周一
# 修正逻辑:我们要找的是“当前月”的第一个周一
# 11月1日是周三(weekday=2)
# 我们要找到11月6日(周一)
# 6 - 1 = 5天
# 所以要加 (7 - 2) % 7 = 5 天
days_to_add = (7 - first_of_next_month.weekday()) % 7
# 但如果1号就是周一(weekday=0), (7-0)%7 = 0, 这是正确的
first_monday = first_of_next_month + timedelta(days=days_to_add)
print(f"{dt} 所在月的第一个周一: {first_monday}") # 应该是 2025-11-06
常见错误与注意事项
-
replace()不会自动进位 如果你尝试将秒设置为 60,它不会自动变成 1 分钟,这可能会导致无效的时间。# 错误示例 dt = datetime(2025, 1, 1, 23, 59, 59) # 下面的代码会抛出 ValueError: second must be in 0..59 # dt.replace(second=60) # 正确做法是手动计算或使用 timedelta dt_plus_one_sec = dt + timedelta(seconds=1) print(dt_plus_one_sec) # 输出: 2025-01-02 00:00:00
-
replace()不会改变原始对象replace()总是返回一个新的datetime对象,原始对象保持不变,这是一个很好的编程实践,因为它避免了意外的副作用。 -
timedelta的精度timedelta的内部存储是以天和秒(包括微秒)为单位的,当你创建一个timedelta时,timedelta(hours=25),它会被正确地转换为1 day, 1 second。
(图片来源网络,侵删)
| 方法 | 用途 | 示例 | 特点 |
|---|---|---|---|
replace() |
绝对修改:设置一个特定的年、月、日、时等。 | dt.replace(year=2025, month=5) |
创建一个新对象,精确控制每个部分,不自动进位。 |
timedelta |
相对修改:增加或减少一个时间间隔。 | dt + timedelta(days=7) |
用于计算“过去某个时间点”,非常适合日期运算。 |
根据你的需求选择合适的方法:
- 想要设置一个固定的日期或时间?用
replace()。 - 想要计算几天后/几小时前的时间?用
timedelta。
