首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python时间处理指南:datetime & time 模块性能优化全揭秘!

大家好,我是老K。

作为一名老程序员,我深知时间的重要性。不光是生活里时间宝贵,程序世界里时间一样至关重要。想想看,日志记录要时间戳,任务调度要定时,性能分析要计算耗时…… 哪个环节都离不开时间处理。

Python 提供了 datetime 和 time 两个强大的模块来处理时间相关的任务。但说实话,这两个模块刚接触的时候,很容易让人犯迷糊:都是处理时间的,它们有啥区别?啥时候该用哪个?一不小心就踩坑里去了。

今天,老K就来给大家彻底捋一捋 Python 的 datetime 和 time 模块,保证你看完之后,不仅能清晰区分它们的应用场景,还能掌握各种时间处理的技巧,写出更高效、更专业的 Python 代码。

一、初探 datetime 与 time:别再傻傻分不清了!

很多朋友刚开始学 Python 时间处理,最大的困惑就是 datetime 和 time 这俩兄弟长得太像了,功能又似乎有重叠,到底该怎么选?

简单来说,你可以这样理解:

time 模块: 更偏底层,主要和 时间戳 打交道,关注的是 绝对时间。它更接近计算机系统的时间概念,精度更高,但对人类来说可能不太直观。

datetime 模块: 更偏高层,更符合人类的 日期和时间 概念,关注的是 日历时间。它提供了更丰富的功能,比如日期计算、格式化等等,用起来更方便。

打个比方,time 模块就像是秒表,记录的是从某个特定时间点(通常是 1970 年 1 月 1 日)到现在经过了多少秒。而 datetime 模块更像是日历,告诉你今天是几月几号,现在几点几分。

二、datetime 模块:日期时间处理的瑞士军刀

datetime 模块绝对是 Python 时间处理的重头戏,它功能强大,使用频率非常高。我们先来看看 datetime 模块里几个核心的类:

datetime.datetime 类: 这是最常用的类,它同时包含了 日期时间 信息,精确到微秒。

datetime.date 类: 只包含 日期 信息,年、月、日。

datetime.time 类: 只包含 时间 信息,时、分、秒、微秒。

datetime.timedelta 类: 表示 时间间隔,可以用来进行日期时间的加减运算。

datetime.timezone 类: 用于处理 时区 信息(虽然在实际应用中,我们可能更多会用到第三方库如 pytz 或 Python 3.9+ 的 zoneinfo,但 datetime.timezone 是基础)。

1. 创建 datetime 对象:花式操作,总有一种适合你

创建 datetime 对象有很多种方法,我们来逐一看看:

获取当前日期时间:datetime.datetime.now()

这是最常用的方法,直接获取当前的本地日期和时间。

import datetime

now = datetime.datetime.now()

print(now) # 例如:2023-10-27 10:30:00.123456

指定日期时间:datetime.datetime(year, month, day, hour, minute, second, microsecond)

你可以手动指定年、月、日、时、分、秒、微秒来创建 datetime 对象。

dt = datetime.datetime(2023, 10, 27, 10, 30, 0)

print(dt) # 输出:2023-10-27 10:30:00

从时间戳创建:datetime.datetime.fromtimestamp(timestamp)

时间戳(timestamp)就是 time.time() 返回的浮点数,你可以用它来创建 datetime 对象。

import time

timestamp = time.time()

dt_from_timestamp = datetime.datetime.fromtimestamp(timestamp)

print(dt_from_timestamp) # 输出当前时间对应的 datetime 对象

从字符串解析:datetime.datetime.strptime(date_string, format)

这个方法非常重要!它能把符合特定格式的字符串解析成 datetime 对象。format 参数指定了字符串的格式。

date_str = "2023-10-27 10:30:00"

dt_from_str = datetime.datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")

print(dt_from_str) # 输出:2023-10-27 10:30:00

这里 %Y、%m、%d、%H、%M、%S 都是 格式化指令,它们分别代表年、月、日、时、分、秒。常用的格式化指令有很多,后面我们会详细介绍。

2. 格式化 datetime 对象:让时间展示更友好

创建了 datetime 对象,我们通常需要把它转换成字符串来展示,或者写入日志等等。这时就要用到 strftime(format) 方法,它和 strptime() 刚好相反,是把 datetime 对象格式化成字符串。

strftime(format):datetime 对象 -> 字符串

now = datetime.datetime.now()

formatted_str = now.strftime("%Y年%m月%d日 %H:%M:%S")

print(formatted_str) # 例如:2023年10月27日 10:30:00

常用的格式化指令包括:

%Y:四位年份(例如 2023)

%y:两位年份(例如 23)

%m:月份(01-12)

%d:日(01-31)

%H:小时(24小时制,00-23)

%I:小时(12小时制,01-12)

%M:分钟(00-59)

%S:秒(00-59)

%f:微秒(000000-999999)

%a:简写星期名(例如 Mon, Tue)

%A:完整星期名(例如 Monday, Tuesday)

%b:简写月份名(例如 Jan, Feb)

%B:完整月份名(例如 January, February)

%c:本地日期和时间表示

%x:本地日期表示

%X:本地时间表示

记住这些常用的格式化指令,基本上就能满足日常需求了。

3. 时间运算:timedelta 大显身手

datetime 模块的另一个亮点是 timedelta 类,它可以方便地进行日期时间的加减运算,计算时间间隔。

创建 timedelta 对象:datetime.timedelta(days, seconds, microseconds, milliseconds, minutes, hours, weeks)

delta = datetime.timedelta(days=1, hours=2) # 表示 1 天 2 小时的时间间隔

datetime 对象与 timedelta 对象运算

now = datetime.datetime.now()

one_day_later = now + datetime.timedelta(days=1)

one_hour_earlier = now - datetime.timedelta(hours=1)

print(one_day_later)

print(one_hour_earlier)

time_diff = one_day_later - now # 计算两个 datetime 对象的时间差,结果是 timedelta 对象

print(time_diff)

print(time_diff.days) # 获取天数差

print(time_diff.seconds) # 获取秒数差 (不包括天数和分钟等)

timedelta 对象还可以进行比较运算,比如判断一个时间间隔是否大于另一个时间间隔等等。

三、time 模块:更底层的选择,追求效率的利器

相比 datetime,time 模块更偏底层,它主要围绕 时间戳时间元组 这两个概念展开。

时间戳(Timestamp): 一个浮点数,表示从 epoch (通常是 1970-01-01 00:00:00 UTC) 到现在的秒数。time.time() 函数可以获取当前的时间戳。

时间元组(Time Tuple): 一个包含 9 个元素的元组,表示时间的各个组成部分,例如年、月、日、时、分、秒等等。time.localtime() 和 time.gmtime() 可以将时间戳转换成时间元组。

1. 常用 time 模块函数

time.time():获取当前时间戳

timestamp = time.time()

print(timestamp) # 输出当前时间戳,例如 1698364200.123456

time.sleep(seconds):程序休眠

让程序暂停执行指定的秒数,常用于控制程序执行速度,或者模拟等待场景。

print("开始休眠...")

time.sleep(2) # 休眠 2 秒

print("休眠结束!")

time.localtime([seconds]):时间戳 -> 本地时间元组

将时间戳转换为本地时区的时间元组。如果不传入时间戳,则默认使用当前时间。

local_time_tuple = time.localtime()

print(local_time_tuple) # 输出本地时间元组

time.gmtime([seconds]):时间戳 -> UTC 时间元组

和 localtime() 类似,但返回的是 UTC 时区的时间元组。

utc_time_tuple = time.gmtime()

print(utc_time_tuple) # 输出 UTC 时间元组

time.mktime(time_tuple):本地时间元组 -> 时间戳

将本地时间元组转换为时间戳,是 localtime() 的反向操作。

time_tuple = time.localtime()

timestamp_from_tuple = time.mktime(time_tuple)

print(timestamp_from_tuple) # 输出时间戳

time.strftime(format[, time_tuple]):时间元组 -> 格式化字符串

将时间元组格式化成字符串,格式化指令和 datetime.strftime() 基本一致。

time_tuple = time.localtime()

formatted_time_str = time.strftime("%Y-%m-%d %H:%M:%S", time_tuple)

print(formatted_time_str) # 输出格式化后的时间字符串

time.strptime(string[, format]):格式化字符串 -> 时间元组

将格式化字符串解析成时间元组,是 strftime() 的反向操作,格式化指令也和 datetime.strptime() 基本一致。

time_str = "2023-10-27 10:30:00"

time_tuple_from_str = time.strptime(time_str, "%Y-%m-%d %H:%M:%S")

print(time_tuple_from_str) # 输出时间元组

2. time 模块的应用场景

time 模块由于更偏底层,精度更高,通常在以下场景中会更有优势:

性能测试和基准测试: 需要精确测量代码执行时间时,time.time() 的纳秒级精度能提供更准确的结果。

系统级编程: 和操作系统底层时间相关的操作,比如文件时间戳、系统定时器等。

高并发、高性能场景: 在对性能要求极致的场景下,time 模块的一些函数可能比 datetime 模块更高效。

四、性能优化:让你的时间处理飞起来

虽然 datetime 和 time 模块本身性能已经不错,但在某些对性能敏感的场景下,我们仍然可以采取一些优化措施:

选择合适的模块: 如果只需要时间戳,或者对精度要求很高,优先考虑 time 模块。如果需要处理日期、时间、时区等复杂逻辑,datetime 模块更方便,但可能会稍慢一些。

减少字符串解析和格式化: strptime() 和 strftime() 这两个函数相对来说比较耗时,尤其是在循环中频繁调用时。尽量避免不必要的字符串转换。

优化 strptime(): 如果需要解析大量时间字符串,可以考虑预编译格式化字符串,或者使用更高效的第三方库,比如 ciso8601,它专门针对 ISO 8601 格式的时间字符串做了优化,速度非常快。

import ciso8601

date_str = "2023-10-27T10:30:00Z"

dt_from_str = ciso8601.parse_datetime(date_str)

print(dt_from_str)

优化 strftime(): 如果只是为了日志输出或者简单的展示,可以考虑使用预定义的格式,或者直接使用 datetime 对象的属性(例如 year、month、day 等)拼接字符串,避免频繁调用 strftime()。

缓存时间戳: 如果需要多次获取当前时间戳,可以考虑将 time.time() 的结果缓存起来,避免重复调用。

使用时间戳进行比较和计算: 时间戳本质上是一个数字,直接进行数值比较和运算效率很高。在需要频繁比较或者计算时间间隔的场景下,可以先把 datetime 对象转换成时间戳,再进行操作。

注意时区转换的开销: 时区转换是一个相对耗时的操作,如果不需要处理时区,尽量避免进行时区转换。

五、总结与最佳实践

掌握 datetime 和 time 模块是 Python 程序员的必备技能。记住以下几点,可以让你在时间处理方面更加游刃有余:

理解 datetime 和 time 的区别: datetime 面向日历时间,功能丰富;time 面向时间戳,更底层,更高效。

灵活运用 datetime 模块的各种类和方法: datetime.datetime、datetime.date、datetime.time、datetime.timedelta,以及 strptime()、strftime() 等方法,根据场景选择最合适的工具。

在性能敏感的场景下,考虑 time 模块和性能优化技巧: 例如使用时间戳、避免频繁的字符串转换、选择高效的解析库等等。

善用第三方库: 例如 pytz、zoneinfo(Python 3.9+)、dateutil、ciso8601 等,它们在时区处理、日期解析等方面提供了更强大的功能和更好的性能。

时间处理看似简单,实则暗藏玄机。希望今天的这篇攻略能帮你扫清 Python 时间处理的盲区,让你在时间的世界里自由驰骋!

如果觉得这篇文章对你有帮助,记得点赞收藏! 你在时间处理方面有什么经验或者踩过什么坑,欢迎在评论区分享,一起交流学习!

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OsHzWJMrVhDgifAp0wEYhc8A0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券