Skip to content

Python 3 - 日期与时间

处理日期和时间是编程中的常见任务。Python 提供了强大的内置模块,如 datetime、time 和 calendar,可以有效地管理日期和时间操作,包括格式化和时区转换。

计算机通常将特定的时间点表示为一个单一数字:自一个称为 ‘epoch’ 的参考点以来经过的总秒数。对于基于 Unix 的系统(包括 Linux 和 macOS),通常还有 Windows,这个 epoch 是指协调世界时(UTC)的 1970 年 1 月 1 日 00:00:00。

Python 的 time 模块提供了 time.time() 函数,该函数返回当前时间,表示自 epoch 以来的秒数,是一个浮点数。这通常被称为 ‘Unix 时间戳’ (Unix timestamp)。

#!/usr/bin/env python3
import time
# 获取当前时间戳(自 epoch 以来的秒数)
current_timestamp = time.time()
print(f"Seconds since January 1, 1970: {current_timestamp}")

输出将是一个很大的数字,每秒都在增加:

Seconds since January 1, 1970: 1678886400.123456

虽然时间戳对于计算和存储很有用,但它们不易于人类阅读。另外请注意,虽然基于 32 位整数的时间戳存在限制(“2038 年问题”),但现代系统通常使用 64 位表示,极大地扩展了可表示的时间范围。

对于大多数日期和时间操作,datetime 模块比 time 模块更直观且功能更强大。它提供了用于处理日期、时间和时间间隔的类。

  • datetime.date: 表示一个日期(年、月、日)。
  • datetime.time: 表示一个时间(小时、分钟、秒、微秒)。
  • datetime.datetime: 表示日期和时间。
  • datetime.timedelta: 表示两个日期或时间之间的持续时间或差值。
  • datetime.timezone: 表示时区信息(在 Python 3.9+ 中通过 zoneinfo 模块进一步增强)。
#!/usr/bin/env python3
import datetime
# 获取当前日期和时间
now = datetime.datetime.now()
print(f"Current date and time: {now}")
# 仅获取当前日期
today = datetime.date.today()
print(f"Current date: {today}")
# 创建一个特定日期
specific_date = datetime.date(2024, 3, 15)
print(f"Specific date: {specific_date}")

输出:

Current date and time: 2024-03-15 10:30:00.123456
Current date: 2024-03-15
Specific date: 2024-03-15

通常,您需要以特定格式显示日期和时间。strftime() 方法将一个 datetime 对象格式化为字符串,而 strptime() 方法则根据格式代码将字符串解析为 datetime 对象。

#!/usr/bin/env python3
import datetime
now = datetime.datetime.now()
# 格式化示例
print(f"Standard format: {now}")
print(f"MM/DD/YY: {now.strftime('%m/%d/%y')}")
print(f"Full month name, day, year: {now.strftime('%B %d, %Y')}")
print(f"Time (HH:MM:SS): {now.strftime('%H:%M:%S')}")
print(f"Date and Time (ISO 8601): {now.isoformat()}") # 标准格式

输出(示例):

Standard format: 2024-03-15 10:45:12.123456
MM/DD/YY: 03/15/24
Full month name, day, year: March 15, 2024
Time (HH:MM:SS): 10:45:12
Date and Time (ISO 8601): 2024-03-15T10:45:12.123456

您可以在 Python 文档中找到完整的格式代码列表:strftime() 和 strptime() 格式代码。

正确处理时区对于许多应用程序至关重要。Python 3.9 引入了 zoneinfo 模块,它使用系统的 IANA 时区数据库。对于较旧的 Python 版本或复杂场景,通常使用第三方库 pytz。

#!/usr/bin/env python3
import datetime
# zoneinfo 需要 Python 3.9+ 版本,某些系统可能需要安装 tzdata 包
# pip install tzdata
from zoneinfo import ZoneInfo
# 获取 UTC 时间
utc_now = datetime.datetime.now(datetime.timezone.utc)
print(f"UTC Time: {utc_now}")
# 转换为特定时区
ny_tz = ZoneInfo("America/New_York")
ny_now = utc_now.astimezone(ny_tz)
print(f"New York Time: {ny_now}")
# 直接创建一个带有时间戳的 datetime 对象
london_time = datetime.datetime(2024, 3, 15, 12, 0, 0, tzinfo=ZoneInfo("Europe/London"))
print(f"London Time: {london_time}")

输出(示例):

UTC Time: 2024-03-15 15:05:30.123456+00:00
New York Time: 2024-03-15 11:05:30.123456-04:00
London Time: 2024-03-15 12:00:00+00:00

注意:时区规则(例如夏令时)很复杂且会变化。使用 zoneinfo 或可靠的库(如 pytz)有助于管理这种复杂性。

虽然通常推荐使用 datetime,但 time 模块提供了更底层的函数,通常直接与操作系统的时间功能交互。它使用一种称为 struct_time 的表示。

time 模块中的几个函数返回或操作时间,使用 time.struct_time 对象。这本质上是一个命名元组 (named tuple),包含 9 个元素:

索引属性字段值
0tm_year年例如,2024
1tm_mon月1 到 12
2tm_mday日1 到 31
3tm_hour时0 到 23
4tm_min分0 到 59
5tm_sec秒0 到 61(60/61 用于闰秒)
6tm_wday周几0 到 6(周一为 0)
7tm_yday一年中的第几天1 到 366
8tm_isdst夏令时标志0 (否), 1 (是), -1 (未知)

示例:获取本地时间作为 struct_time

Section titled “示例:获取本地时间作为 struct_time”
#!/usr/bin/env python3
import time
# 获取当前时间戳
current_timestamp = time.time()
# 将时间戳转换为本地 struct_time
local_time_struct = time.localtime(current_timestamp)
print(f"Local time (struct_time): {local_time_struct}")
# 访问特定字段
print(f"Year: {local_time_struct.tm_year}")
print(f"Hour: {local_time_struct.tm_hour}")
# 将时间戳转换为 UTC struct_time
gmt_time_struct = time.gmtime(current_timestamp)
print(f"UTC time (struct_time): {gmt_time_struct}")

输出(示例):

Local time (struct_time): time.struct_time(tm_year=2024, tm_mon=3, tm_mday=15, tm_hour=11, tm_min=10, tm_sec=5, tm_wday=4, tm_yday=75, tm_isdst=1)
Year: 2024
Hour: 11
UTC time (struct_time): time.struct_time(tm_year=2024, tm_mon=3, tm_mday=15, tm_hour=15, tm_min=10, tm_sec=5, tm_wday=4, tm_yday=75, tm_isdst=0)

time 模块中的关键函数包括:

函数描述
time.sleep(secs)暂停执行指定的秒数。
time.strftime(format[, t])根据格式代码将 struct_time(如果省略 t,则为当前本地时间)格式化为字符串。
time.strptime(string, format)根据格式将表示时间的字符串解析为 struct_time。
time.mktime(t)将本地 struct_time 转换为自 epoch 以来的秒数(时间戳)。
time.asctime([t])将 struct_time(或当前本地时间)转换为标准的 24 字符字符串格式(例如,‘Fri Mar 15 11:10:05 2024’)。灵活性低于 strftime。
time.ctime([secs])将时间戳(或当前时间)转换为标准的 24 字符字符串格式。等同于 asctime(localtime(secs))。
time.perf_counter()返回高分辨率性能计数器值(用于测量短时间)。
time.process_time()返回当前进程的系统和用户 CPU 时间总和。

注意:time.clock() 在 Python 3.3 中被废弃,在 Python 3.8 中被移除。请改用 time.perf_counter() 或 time.process_time() 进行性能测量。

calendar 模块提供了与日历相关的函数,例如生成月份或年份的文本日历。

#!/usr/bin/env python3
import calendar
# 以字符串形式获取 2024 年 3 月的日历
cal_text = calendar.month(2024, 3)
print("Calendar for March 2024:")
print(cal_text)
# 检查某一年是否是闰年
is_leap = calendar.isleap(2024)
print(f"Is 2024 a leap year? {is_leap}")
# 获取特定日期的工作日(0=周一)
weekday_code = calendar.weekday(2024, 3, 15)
print(f"Weekday for March 15, 2024 (0=Mon): {weekday_code}") # 输出:4(周五)

输出:

Calendar for March 2024:
March 2024
Mo Tu We Th Fr Sa Su
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Is 2024 a leap year? True
Weekday for March 15, 2024 (0=Mon): 4

calendar 模块还提供了诸如 calendar.calendar(year) 用于获取全年日历、calendar.monthrange(year, month) 用于获取月份第一天是周几以及该月有多少天,以及 calendar.setfirstweekday() 用于更改周的起始日。

  • 日志记录: 标记事件发生的时间。
  • 任务调度: 在特定时间或间隔运行代码。
  • 数据分析: 分析时间序列数据。
  • Web 开发: 处理会话过期、设置 cookie 生命周期、显示时间戳。
  • 计算持续时间: 计算事件之间的时间差。
  • 用户界面: 以用户友好的格式显示日期和时间。