1. 写在前面
关于时间相关的处理无处不在, 比如日志管理必然要记录时间, 统计程序执行开始、结束时间, 测试函数的执行时长, 在时间序列的相关分析上, 也往往用到python的时间模块和pandas的时间处理相结合, 所以了解python时间模块的一些常用操作也是非常重要的,。
这篇文章就小总一下python的时间模块的使用方法, 同样 依然是从使用的角度出发。
python与时间处理相关的模块有两个: time模块和datetime模块。
time模块提供两种时间表达方式(假定一个零点基准,偏移长度换算为按秒的数值型和由 9 个整数组成的元组 struct_time 表示的时间), 前面这种一般在测试函数的执行时长时候用到, 后者比较常用。
datetime模块, 常用类4个(date, time, datetime, timedelta), 后面会一一看看常用的操作
最后再整理一个calendar, 这里面也是提供了一些挺有意思的功能。
Ok, let’s go!
2. time模块
使用之前, 要导入时间模块
import time
time模块提供了时间相关的类和函数。 常用的就是一个类struct_time, 这里面有表示时间的9个整数组成的元组。 关于time模块, 常用的是下面的5个函数:
# 当前时间浮点数 time() second = time.time() # 1592451544.5129032
这个一般在测试函数执行速度的时候用到, 在函数执行前用start统计当前时间, 函数执行完毕用end统计当前时间, 然后两者一减就可以看出该函数的执行速度。
# 时间数组 localtime() 这个函数就可以把上面的这种浮点转成struct_time local_time = time.localtime(second) local_time # 这里面就可以获取相应的属性, tm_wday表示周几, tm_yday表示一年的第多少天 ## 结果: time.struct_time(tm_year=2020, tm_mon=6, tm_mday=18, tm_hour=10, tm_min=21, tm_sec=56, tm_wday=3, tm_yday=170, tm_isdst=0)
通过相应的属性名就可以获取相应的时间值, 但是这个看起来依然不是我们想要的时间格式, 那么我们就可以用下面的两个函数获取我们看的比较顺眼的时间格式:
# 时间字符串 time 类 asctime 方法,转换 struct_time 为时间字符串 str_time = time.asctime(local_time) str_time # 'Thu Jun 18 10:21:56 2020' # 如果上面的还不顺眼, 可以自己格式化时间 # 格式化字符串 time 类 strftime 方法,按照时间格式要求,格式化 struct_time 为时间字符串 format_time = time.strftime('%Y-%m-%d %H:%M:%S', local_time) format_time # '2020-06-18 10:21:56'
这样是不是好看多了。下面再介绍一个,就是把这种格式再变回到struct_time的那种格式:
# 字符时间转时间数组 strptime() str_to_struct = time.strptime(format_time, '%Y-%m-%d %H:%M:%S') # 注意:第二个参数的时间格式,要匹配上第一个参数的时间格式。 str_to_struct ## 结果: time.struct_time(tm_year=2020, tm_mon=6, tm_mday=18, tm_hour=10, tm_min=21, tm_sec=56, tm_wday=3, tm_yday=170, tm_isdst=-1)
最后还要记住常用的时间格式:
%Y :年
%m :月 取值 [01,12]
%d :天 取值 [01,31]
%H :小时 取值 [00,23]
%M :分钟 取值 [00,59]
%S :秒 取值 [00,61] 闰秒
关于时间模块, 比较常用的就这5个函数了。
3. datetime模块
datetime模块里面有四个常用类, date, datetime, time, timedelta。
date: 日期类, 包括属性年月日及相关方法
time: 时间类, 包括属性时分秒及相关方法
datetime: 日期时间,继承于 date,包括属性年、月、日、时、分、秒等及相关方法,其中年月日必须参数
timedelta: 两个 datetime 值的差,比如相差几天(days)、几小时(hours)、几分(minutes)等
看起来挺复杂, 但是从使用的角度来看, 用到的东西也不是太多, 下面一一来看, 首先依然是先导入:
from datetime import date, time, datetime, timedelta
date: date表示日期, 能用的无非是打印当前日期, 当前日期转成格式字符串, 然后再变回去, 方法和上面time模块里面的差不多。
# 打印当前日期 tod = date.today() tod # datetime.date(2020, 6, 18) # 当前日期字符串 str_date = date.strftime(tod, '%Y-%m-%d') str_date # '2020-06-18' # 字符日期转日期 # date 类里没有 strptime 方法,它的子类 datetime 才有解析字符串日期的方法 strptime。 str_to_date = datetime.strptime('2020-02-22', '%Y-%m-%d') str_to_date # datetime.datetime(2020, 2, 22, 0, 0)
datetime: 这个类继承于date, 并且在日期的基础上加上了time。 常用的依然是获取当前时间, 当前时间格式化, 然后再变回去。
# 打印当前时间 right = datetime.now() right # datetime.datetime(2020, 6, 18, 10, 31, 43, 759828) # 当前时间转字符串显示 str_time = datetime.strftime(right, '%Y-%m-%d %H:%M:%S') str_time # '2020-06-18 10:31:43' # 当前时间转字符串显示 str_time = datetime.strftime(right, '%Y-%m-%d %H:%M:%S') str_time # datetime.datetime(2020, 6, 18, 10, 31, 43)
timedelta: 求两个 datetime 类型值的差,返回差几天:days,差几小时:hours 等. 相减的两个时间,不能一个为 date 类型,一个为 datetime 类型,尽管两个类型是父子关系。
d1 = datetime.today() d2 = d1 - timedelta(hours=10) print(d1, d2) # 2020-06-18 11:08:26.659060 2020-06-18 01:08:26.659060
这个在时间序列的数据处理上也是非常常用的, 和pandas的pd.DateOffset类似, 可以计算时间差, 尤其是做滞后特征的时候。
4. Calendar模块
这个模块也有一些有意思的小案例,比如打印个日历, 判断是否闰年, 判断一个月有几天, 获取到月的第一天和最后一天。 下面一一来看:
绘制某一年的日历图
import calendar year_calerdar_str = calendar.calendar(2020) print(year_calerdar_str)
可以看一下效果:
绘制某一个月的日历图
# 月的日历图 month_calendar_str = calendar.month(2020, 6) print(month_calendar_str) 这样会单独打印某个月的日历图。 判断某一年是否闰年(之前都是写代码判断的, 什么能被4整除或者不能被4整除但是能被400整除啥的, 现在竟然有包可调) # 判断是否闰年 is_leap = calendar.isleap(2020) is_leap # True 判断一个月有几天 # 判断月有几天 mydate = date.today() weekday, days = calendar.monthrange(mydate.year, mydate.month) print(weekday, days) # weekday表示该月的第一天是周几, days表示该月有多少天 # 结果: 0 30 月的第一天和最后一天 # 月的第一天和最后一天 mydate = date.today() # 第一天 month_first_day = date(mydate.year, mydate.month, 1) # 最后一天 _, days = calendar.monthrange(mydate.year, mydate.month) month_last_day = date(mydate.year, mydate.month, days) print(month_first_day, month_last_day)
好了, 关于python时间模块常用的一些操作先整理到这里, 最后给出一个案例,这个案例可以帮忙算算从现在开始还有几天是女朋友的生日, 这样每天算一遍, 就不会忘了, 哈哈。
import re # 计算女朋友的生日离现在还有几天 def get_days(birthday:str)->int: splits = re.split(r'[-.\s+/]', birthday) splits = [s for s in splits if s] if len(splits) < 3: raise ValueError('输入格式不正确, 至少包括年月日') splits = splits[:3] # 只截取年月日 birthday = datetime.strptime('-'.join(splits), '%Y-%m-%d') tod = date.today() delta = birthday.date() - tod return delta.days get_days('2020-09-24') # 98
更多Python知识,请关注!!