处理日期和时间看起来很简单,直到您开始面对各种格式、时区、夏令时规则,或来自多个系统的时间戳。这时就不能再将时间当作原始字符串或整数来存储了。Python 的 datetime 模块正是为了帮助您以可预测的方式管理这些要素。
本指南将讲解核心类、如何创建并使用 datetime 对象、如何进行运算、如何格式化与解析值、处理时区等。每一部分都循序渐进,帮助您从基础操作过渡到更高级的用法。
Python datetime 模块的核心类
在着手具体操作之前,先理解 Python 在概念层面如何建模日期与时间会很有帮助。datetime 模块只用了一小组类,每个类都聚焦于问题的一个方面。理解各类的定位,能让后续流程更顺畅。
date
当您只需要日历日期,而不用考虑一天中的时间或时区时,date 类就是所需。它用直观的属性表示年、月、日。
其属性包括:
以及方法:
today()
fromisoformat()
replace()
isoformat()
weekday()
isoweekday()
from datetime import date
d = date( 2025 , 3 , 1 )
print ( d) 技术支持
这段代码创建了一个简单的日历日期。如果输入无效组合(如 February 30),Python 会抛出 ValueError。
time
有些任务只关心一天中的时间,比如一个在下午 2:30 运行的提醒。time 类很有用,因为它存储小时、分钟、秒,以及(此例不需要的)微秒或时区数据。
其属性包括:hour、minute、second、microsecond、tzinfo
其方法包括:replace()、isoformat()
from datetime import time
t = time( 14 , 30 , 15 )
print ( t) 技术支持
这会创建一个不带日期的时刻。无效值(如 hour=27)会产生错误。
datetime
大多数真实场景都需要同时包含日期和时间,这正是 datetime 的用武之地。它是该模块中最通用的类,也是您在日志、处理与协调事件时最常用的类。
其属性(在上述基础上另加):tzinfo
其方法包括 now()、utcnow()、fromisoformat()、strptime()、strftime()、astimezone() 。它还支持与 timedelta 的算术运算,后文将更详细介绍。
from datetime import datetime
dt = datetime( 2025 , 3 , 1 , 14 , 30 )
print ( dt) 技术支持
这会生成一个完整的时间戳,包含日期和时间两个部分。
timedelta
每当您需要衡量经过的时间或将某个时间戳向前或向后偏移时,timedelta 就是正确选择。它表示一个时长,而非具体时刻。
其属性包括:days、seconds、microseconds。 常用于偏移、时间差和调度逻辑。
from datetime import timedelta
delta = timedelta( days= 7 , hours= 3 )
print ( delta) 技术支持
这表示一个固定时长。当与 datetime 相加或相减时尤其有用。
tzinfo
tzinfo 定义了 Python 的时区接口。您通常不会直接创建它们,但在附加或转换时区时,datetime 系统会用到它们。
timezone
timezone 是一个内置的 tzinfo 实现,用于像 UTC 或 UTC+1 这样的固定 UTC 偏移。对于不涉及夏令时规则的简单场景很实用。
创建与访问 Python datetime 对象
了解了这些类之后,下一步就是学习如何创建它们的实例。Python 提供了多种方式,取决于数据来源:手动输入、系统时间、时间戳或文本。
使用类构造函数
构造函数让您可以完全掌控要创建的值。这通常是构建 date、time 或 datetime 对象最明确、最不易出错的方式。
from datetime import date
d = date( 2025 , 3 , 1 )
print ( d) 技术支持
这直接构建了一个日历日期。无效值会立即抛出错误,有助于及早发现问题。
from datetime import time
t = time( 14 , 30 , 15 )
print ( t) 技术支持
这会生成一个一天中的时间值。当您不需要附带日期时使用它。
from datetime import datetime
dt = datetime( 2025 , 3 , 1 , 14 , 30 )
print ( dt) 技术支持
这会创建一个完整的时间戳。添加 tzinfo 参数可使其具备时区感知能力。
基于时间戳创建
Unix 时间戳在日志、API 和操作系统中十分常见。Python 可以轻松将其转换为可读的 datetime 对象。
datetime. fromtimestamp( 1700000000 )
datetime. utcfromtimestamp( 1700000000 ) 技术支持
第一种在本地时间下解释时间戳;第二种在 UTC 下解释。
获取当前值的类方法
当您需要当前日期或时间时,Python 提供了简洁的辅助方法。它们对日志、事件跟踪和实时管道至关重要。
from datetime import datetime, date, timezone
print ( date. today( ) )
print ( datetime. now( ) )
print ( datetime. now( tz= timezone. utc) ) 技术支持
这些方法会返回当前系统时间,可根据需要选择本地时间或 UTC。
datetime. fromtimestamp( 1700000000 )
datetime. utcfromtimestamp( 1700000000 ) 技术支持
这些方法将纪元时间戳转换为 datetime 对象。在解析 API 或数据库值时非常常见。
从字符串解析
真实世界的数据集常把时间戳存成文本。Python 提供了可靠工具,把这些字符串转换为结构化的值。
strptime( )
from datetime import datetime
dt = datetime. strptime( "2025-03-01 14:30" , "%Y-%m-%d %H:%M" )
print ( dt) 技术支持
strptime() 使用格式模式解析字符串。如果字符串不完全匹配,Python 会抛出 ValueError。
from datetime import datetime
dt = datetime. strptime( "not-a-date" , "%Y-%m-%d" ) 技术支持
这会失败,因为输入与预期模式不匹配。
fromisoformat( )
datetime. fromisoformat( "2025-03-01T14:30:00" ) 技术支持
ISO 8601 字符串解析顺畅,因为其结构已标准化。这通常是从 API 或现代数据管道加载时间戳的最简方式。
进行日期运算
学会创建时间戳之后,下一步就是对其进行操作。您可以通过计算时长、移动日期或比较时间区间来完成这些工作。
用于时间计算的 Timedelta
timedelta 用于表示固定时长的区间,如“5 小时”或“2 周”。这些区间有助于调度、记录日志,或实现简单倒计时。
from datetime import datetime, timedelta
dt = datetime( 2025 , 3 , 1 , 14 , 30 )
new_dt = dt + timedelta( days= 5 )
print ( new_dt) 技术支持
此示例将时间戳向前移动五天。
start = datetime( 2025 , 3 , 1 , 9 , 0 )
end = datetime( 2025 , 3 , 1 , 14 , 30 )
duration = end - start
print ( duration. total_seconds( ) ) 技术支持
这里,两个 datetime 相减会得到一个 timedelta,您可以将其转换为秒、天或小时。
固定时长 vs. 感知日历的运算
时间单位并非均等。月份长度不同、闰年会多一天,而月末的处理也可能难以预测。对于这些情况,timedelta 并不够用。
dateutil.relativedelta 可处理“感知日历”的运算:
from dateutil. relativedelta import relativedelta
from datetime import date
d = date( 2025 , 1 , 31 )
print ( d + relativedelta( months= 1 ) ) 技术支持
这能正确处理不存在的“2 月 31 日”,通过恰当方式移动日期。
格式化与解析日期
日期时间格式几乎无处不在:API 需要特定格式,用户偏好可读文本,日志依赖一致的时间戳字符串。Python 同时支持灵活格式化与标准化表示。
使用 strftime 进行字符串格式化
strftime() 允许您用预定义代码将 datetime 对象转为格式化字符串。
from datetime import datetime
dt = datetime( 2025 , 3 , 1 , 14 , 30 )
print ( dt. strftime( "%A, %B %d, %Y at %H:%M" ) ) 技术支持
这会打印一个包含星期几和完整月份名称的可读字符串。
dt. strftime( "%Y-%m-%dT%H:%M:%S" ) 技术支持
这会生成适合数据存储或 API 的类 ISO 字符串。
使用 strptime 解析字符串
from datetime import datetime
dt = datetime. strptime( "2025-03-01 14:30" , "%Y-%m-%d %H:%M" )
print ( dt) 技术支持
这会把文本转换为 datetime 对象。字符串与模式的任何不匹配都会引发错误。
使用 ISO 8601 与 RFC 3339
ISO 8601 解决了很多地区性日期格式的歧义。Python 原生支持它:
from datetime import datetime
dt = datetime. fromisoformat( "2025-03-01T14:30:00" )
print ( dt. isoformat( ) ) 技术支持
这是在系统、API 或数据库之间交换数据时最安全的格式。
处理时区
时区为时间处理带来了最棘手的一些问题。Python 通过区分朴素(naive)与具备时区感知(aware)的 datetime 对象,并提供工具来处理真实世界的时区,从而加以应对。
朴素对象 vs. 具备时区感知的对象
朴素的 datetime 不带时区:
from datetime import datetime
naive_dt = datetime( 2025 , 3 , 1 , 14 , 30 )
print ( naive_dt. tzinfo) 技术支持
具备时区感知的 datetime 包含时区偏移:
from datetime import timezone, timedelta
aware_dt = naive_dt. replace( tzinfo= timezone( timedelta( hours= 1 ) ) )
print ( aware_dt) 技术支持
在比较或运算中混用朴素与感知对象通常会导致错误。
使用 zoneinfo 模块
Python 的 zoneinfo 模块提供对现实世界 IANA 时区的访问:
from zoneinfo import ZoneInfo
from datetime import datetime
dt = datetime( 2025 , 3 , 1 , 14 , 30 , tzinfo= ZoneInfo( "Europe/Paris" ) )
print ( dt) 技术支持
时区转换很简单:
dt. astimezone( ZoneInfo( "America/New_York" ) ) 技术支持
这会在不同的本地时区中表达同一时刻。
在时区之间转换
您可以使用 astimezone() 将任何具备时区感知的时间戳转换到另一时区:
from zoneinfo import ZoneInfo
dt_ny = dt. astimezone( ZoneInfo( "America/New_York" ) )
print ( dt_ny) 技术支持
一个常见最佳实践是将时间戳以 UTC 存储,只在需要显示时再转换。
比较与筛选日期
比较几乎出现在每个工作流程中。比如对日志排序、筛选事件,或判断某事是否发生在某个阈值之前或之后。
from datetime import datetime
a = datetime( 2025 , 3 , 1 , 12 , 0 )
b = datetime( 2025 , 3 , 1 , 15 , 0 )
print ( a < b) 技术支持
具备时区感知的比较会考虑偏移量:
from datetime import datetime
from zoneinfo import ZoneInfo
dt1 = datetime( 2025 , 3 , 1 , 12 , 0 , tzinfo= ZoneInfo( "Europe/London" ) )
dt2 = datetime( 2025 , 3 , 1 , 7 , 0 , tzinfo= ZoneInfo( "America/New_York" ) )
print ( dt1 == dt2) 技术支持
对集合进行筛选也很自然:
dates = [
datetime( 2025 , 3 , 1 , 10 ) ,
datetime( 2025 , 2 , 20 , 9 ) ,
datetime( 2025 , 3 , 1 , 8 )
]
cutoff = datetime( 2025 , 3 , 1 )
filtered = [ d for d in dates if d >= cutoff]
print ( filtered) 技术支持
在跨时区工作时,将时间统一到 UTC 很有帮助。
更高级的用例
除了基础的解析和运算外,日期时间在许多工作流程中还会以其他形式出现。以下是您经常会遇到的一些模式。
Unix 时间戳
Unix 时间戳以自 1970 年 1 月 1 日(UTC)以来的秒数计量。它们广泛用于系统编程和 API。
from datetime import datetime
dt = datetime. fromtimestamp( 1700000000 )
print ( dt) 技术支持
毫秒与微秒需要进行缩放:
ts_ms = 1700000000000
dt_ms = datetime. fromtimestamp( ts_ms / 1000 )
ts_us = 1700000000000000
dt_us = datetime. fromtimestamp( ts_us / 1_000_000 ) 技术支持
调度与定时器
像 schedule 这样的库依赖 datetime 值来判断任务何时运行。无论是每隔几秒触发函数,还是在当天稍后安排一次性事件,datetime 都为这些比较提供了基础。
数据分析模式
在分组和基于时间的分析中,常从 datetime 中提取属性:
dt = datetime( 2025 , 3 , 1 , 14 , 30 )
print ( dt. year)
print ( dt. isocalendar( ) ) 技术支持
在 pandas 中,按周期重采样非常常见:
import pandas as pd
df = pd. DataFrame( {
"value" : [ 10 , 12 , 15 ] ,
"timestamp" : pd. to_datetime( [
"2025-03-01" ,
"2025-03-02" ,
"2025-03-08"
] )
} ) . set_index( "timestamp" )
print ( df. resample( "W" ) . sum ( ) ) 技术支持
结语
若想进一步学习 datetime,请观看我们课程 Working with Dates and Times in Python (作者:Max Shrom)以及 Jason Myers 的 Data Types for Data Science in Python 中的相关视频。
VIDEO
如果您在字符串转换方面还需要更多帮助,我们的教程 Converting Strings to Dates as datetime Objects 也许对您有用。
处理日期和时间看起来很简单,直到您开始面对各种格式、时区、夏令时规则,或来自多个系统的时间戳。这时就不能再将时间当作原始字符串或整数来存储了。Python 的
datetime模块正是为了帮助您以可预测的方式管理这些要素。本指南将讲解核心类、如何创建并使用
datetime对象、如何进行运算、如何格式化与解析值、处理时区等。每一部分都循序渐进,帮助您从基础操作过渡到更高级的用法。Python datetime 模块的核心类
在着手具体操作之前,先理解 Python 在概念层面如何建模日期与时间会很有帮助。
datetime模块只用了一小组类,每个类都聚焦于问题的一个方面。理解各类的定位,能让后续流程更顺畅。date
当您只需要日历日期,而不用考虑一天中的时间或时区时,
date类就是所需。它用直观的属性表示年、月、日。其属性包括:
yearmonthday以及方法:
today()fromisoformat()replace()isoformat()weekday()isoweekday()这段代码创建了一个简单的日历日期。如果输入无效组合(如
February 30),Python 会抛出ValueError。time
有些任务只关心一天中的时间,比如一个在下午 2:30 运行的提醒。
time类很有用,因为它存储小时、分钟、秒,以及(此例不需要的)微秒或时区数据。其属性包括:
hour、minute、second、microsecond、tzinfo其方法包括:
replace()、isoformat()这会创建一个不带日期的时刻。无效值(如
hour=27)会产生错误。datetime
大多数真实场景都需要同时包含日期和时间,这正是
datetime的用武之地。它是该模块中最通用的类,也是您在日志、处理与协调事件时最常用的类。其属性(在上述基础上另加):
tzinfo其方法包括
now()、utcnow()、fromisoformat()、strptime()、strftime()、astimezone()。它还支持与timedelta的算术运算,后文将更详细介绍。这会生成一个完整的时间戳,包含日期和时间两个部分。
timedelta
每当您需要衡量经过的时间或将某个时间戳向前或向后偏移时,
timedelta就是正确选择。它表示一个时长,而非具体时刻。其属性包括:
days、seconds、microseconds。 常用于偏移、时间差和调度逻辑。这表示一个固定时长。当与 datetime 相加或相减时尤其有用。
tzinfo
tzinfo定义了 Python 的时区接口。您通常不会直接创建它们,但在附加或转换时区时,datetime 系统会用到它们。timezone
timezone是一个内置的tzinfo实现,用于像 UTC 或 UTC+1 这样的固定 UTC 偏移。对于不涉及夏令时规则的简单场景很实用。创建与访问 Python datetime 对象
了解了这些类之后,下一步就是学习如何创建它们的实例。Python 提供了多种方式,取决于数据来源:手动输入、系统时间、时间戳或文本。
使用类构造函数
构造函数让您可以完全掌控要创建的值。这通常是构建 date、time 或 datetime 对象最明确、最不易出错的方式。
这直接构建了一个日历日期。无效值会立即抛出错误,有助于及早发现问题。
这会生成一个一天中的时间值。当您不需要附带日期时使用它。
这会创建一个完整的时间戳。添加
tzinfo参数可使其具备时区感知能力。基于时间戳创建
Unix 时间戳在日志、API 和操作系统中十分常见。Python 可以轻松将其转换为可读的 datetime 对象。
第一种在本地时间下解释时间戳;第二种在 UTC 下解释。
获取当前值的类方法
当您需要当前日期或时间时,Python 提供了简洁的辅助方法。它们对日志、事件跟踪和实时管道至关重要。
这些方法会返回当前系统时间,可根据需要选择本地时间或 UTC。
这些方法将纪元时间戳转换为
datetime对象。在解析 API 或数据库值时非常常见。从字符串解析
真实世界的数据集常把时间戳存成文本。Python 提供了可靠工具,把这些字符串转换为结构化的值。
strptime()使用格式模式解析字符串。如果字符串不完全匹配,Python 会抛出ValueError。这会失败,因为输入与预期模式不匹配。
ISO 8601 字符串解析顺畅,因为其结构已标准化。这通常是从 API 或现代数据管道加载时间戳的最简方式。
进行日期运算
学会创建时间戳之后,下一步就是对其进行操作。您可以通过计算时长、移动日期或比较时间区间来完成这些工作。
用于时间计算的 Timedelta
timedelta用于表示固定时长的区间,如“5 小时”或“2 周”。这些区间有助于调度、记录日志,或实现简单倒计时。此示例将时间戳向前移动五天。
这里,两个 datetime 相减会得到一个 timedelta,您可以将其转换为秒、天或小时。
固定时长 vs. 感知日历的运算
时间单位并非均等。月份长度不同、闰年会多一天,而月末的处理也可能难以预测。对于这些情况,
timedelta并不够用。dateutil.relativedelta可处理“感知日历”的运算:这能正确处理不存在的“2 月 31 日”,通过恰当方式移动日期。
格式化与解析日期
日期时间格式几乎无处不在:API 需要特定格式,用户偏好可读文本,日志依赖一致的时间戳字符串。Python 同时支持灵活格式化与标准化表示。
使用 strftime 进行字符串格式化
strftime()允许您用预定义代码将 datetime 对象转为格式化字符串。这会打印一个包含星期几和完整月份名称的可读字符串。
这会生成适合数据存储或 API 的类 ISO 字符串。
使用 strptime 解析字符串
这会把文本转换为 datetime 对象。字符串与模式的任何不匹配都会引发错误。
使用 ISO 8601 与 RFC 3339
ISO 8601 解决了很多地区性日期格式的歧义。Python 原生支持它:
这是在系统、API 或数据库之间交换数据时最安全的格式。
处理时区
时区为时间处理带来了最棘手的一些问题。Python 通过区分朴素(naive)与具备时区感知(aware)的 datetime 对象,并提供工具来处理真实世界的时区,从而加以应对。
朴素对象 vs. 具备时区感知的对象
朴素的 datetime 不带时区:
具备时区感知的 datetime 包含时区偏移:
在比较或运算中混用朴素与感知对象通常会导致错误。
使用 zoneinfo 模块
Python 的
zoneinfo模块提供对现实世界 IANA 时区的访问:时区转换很简单:
这会在不同的本地时区中表达同一时刻。
在时区之间转换
您可以使用
astimezone()将任何具备时区感知的时间戳转换到另一时区:一个常见最佳实践是将时间戳以 UTC 存储,只在需要显示时再转换。
比较与筛选日期
比较几乎出现在每个工作流程中。比如对日志排序、筛选事件,或判断某事是否发生在某个阈值之前或之后。
具备时区感知的比较会考虑偏移量:
对集合进行筛选也很自然:
在跨时区工作时,将时间统一到 UTC 很有帮助。
更高级的用例
除了基础的解析和运算外,日期时间在许多工作流程中还会以其他形式出现。以下是您经常会遇到的一些模式。
Unix 时间戳
Unix 时间戳以自 1970 年 1 月 1 日(UTC)以来的秒数计量。它们广泛用于系统编程和 API。
毫秒与微秒需要进行缩放:
调度与定时器
像 schedule 这样的库依赖 datetime 值来判断任务何时运行。无论是每隔几秒触发函数,还是在当天稍后安排一次性事件,
datetime都为这些比较提供了基础。数据分析模式
在分组和基于时间的分析中,常从 datetime 中提取属性:
在 pandas 中,按周期重采样非常常见:
结语
若想进一步学习 datetime,请观看我们课程 Working with Dates and Times in Python(作者:Max Shrom)以及 Jason Myers 的 Data Types for Data Science in Python 中的相关视频。
如果您在字符串转换方面还需要更多帮助,我们的教程 Converting Strings to Dates as datetime Objects 也许对您有用。