前言
在程序开发中,对时间的记录和统计是最常用的功能之一,在Python中处理时间的模块则是time和datetime,今天就仔细介绍一下这两个模块的具体使用和转换方法。
time模块
time模块是Python中用于获取时间的最基础的模块,可以满足基本的时间获取、格式化输出等需求。
获取当前时间戳
时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数,因此无法表示1970年之前的日期,2038年以后的日期也不行。
timeStamp = time.time() # //1655623699.2784467
构造时间结构体
所谓时间结构体,就是time.struct_time
类,可以根据时间单位传入时间的数值,得到一个用于表示时间的对象,简单的构造方式如下
timeTuple = (2020, 1, 2, 1, 51, 3, 2, 2, 0) myTime = time.struct_time(timeTuple)
注意传入的参数需要是元组,元组内的9个元素依次分别为年、月、日、时、分、秒、一星期中的第几天、一年中的第几天、是否是夏令时,其中的夏令时使用几率很低,默认填写0就好。
另外其中的一星期中的第几天、一年中的第几天这两个参数要小心填写,因为不会进行校验。
得到时间结构体后就可以通过内置属性获取其中的某个时间单位。
print(myTime.tm_year, myTime.tm_mon, myTime.tm_mday, myTime.tm_hour, myTime.tm_min, myTime.tm_sec, myTime.tm_wday, myTime.tm_yday, myTime.tm_isdst, myTime.tm_mday) # //2020 1 2 1 51 3 2 2 0
其中tm_mday代表了一个月中的第几天。
获取当前时区的时间
time.localtime()
获取当前时区的时间结构体。
可以将时间戳传入,转换成当前时区的时间结构体。
获取格林威治时间
time.gmtime() #1655623699.2784467
获取格林威治时区的时间结构体。
和localtime类似,同样可以将时间戳传入,得到时间戳对应的格林威治时区时间。
时间结构体转时间戳
time.mktime(myTime)
通过time库的mktime方法可以把时间结构体转换成时间戳。
时间戳的简单格式化
time.ctime(timeStamp) #//Mon Jun 20 22:22:01 2022
通过time库的ctime方法可以将时间戳简单格式化,参数为空时默认为当前时间。
时间结构体的简单格式化
time.asctime(myTime) #//Mon Jun 20 22:23:08 2022
通过time库的asctime方法可以将时间结构体简单格式化,参数为空时默认为当前时间。
时间结构体的自定义格式化
我最常用的格式化方式如下
time.strftime("%Y-%m-%d %H:%M:%S", myTime) #//2022-06-20 22:28:07
其中第一个参数为时间的展示格式,常用的参数和对应的含义如下,注意区分大小写:
- %y 两位数的年份表示(00-99)
- %Y 四位数的年份表示(0000-9999)
- %m 月份(01-12)
- %d 月内中的一天(0-31)
- %H 24小时制小时数(00-23)
- %I 12小时制小时数(01-12)
- %M 分钟数(00-59)
- %S 秒数(00-59)
- %a 本地简化星期名称,例如Mon
- %A 本地完整星期名称,例如Monday
- %b 本地简化的月份名称,例如Jan
- %B 本地完整的月份名称,例如January
- %c 本地化的日期表示和时间表示
- %j 年内的天序号(001-366)
- %p 本地A.M.或P.M.的等价符,AM、PM
- %U 一年中的星期数(00-53)星期天为星期的开始
- %w 星期(0-6),星期天为星期的开始,序号0
- %u 星期(1-7),星期一为星期的开始,序号1
- %W 一年中的星期数(00-53)星期一为星期的开始
- %c,简单格式化,例如Sun Jun 19 00:00:00 2022
- %x 本地化的日期表示,例如06/19/2022
- %X 本地化的时间表示,例如12:03:00
- %z UTC偏移量,格式为 ±HHMM[SS[.ffffff]],例如东八区为+0800
- %Z 当前时区的名称
- %% %号本身
其中的数字都有左侧补0填充空值位。
格式化字符串转为时间结构体
相比起通过struct_time
构造时间结构体,通过字符串生成时间结构体的方式更为常用
a = "Sat Mar 28 22:24:24 2016" time.strptime(a,"%a %b %d %H:%M:%S %Y")
显然,strptime方法就是strftime的反向,时间格式参数也相同。
程序等待时间
这算是time库最常用的功能了吧,让程序等待一定的秒数,一般用于延时、等待通信结果等等。
time.sleep(5)
获取程序运行时长
time.process_time()
通过该方法可以很方便地获取Python程序运行时长。
datetime库
相比起time库,datetime库拥有着更加强大的功能,可以对时间对象进行更加复杂的处理,例如时间比较、时间相减等等,适用范围更广。
datetime.date类
date类代表一个理想化历法中的一天的日期,例如2000-03-23,其中的年必须为正整数,所以不支持公元前的表示。
date构建方式
myDate = datetime.date(2020, 2, 10) print(myDate.year, myDate.month, myDate.day) #//2020 2 10
三个参数依次代表年、月、日,得到的日期对象可以通过year、month、day三个内置属性获取对应的时间单位。
两个date对象之间可以比较大小,并可以进行相减运算,得到一个时间段,也就是timedelta对象
,后面会具体介绍,反过来一个date对象可以和时间段进行加减运算得到另一个date对象。
获取该日为星期几
print(myDate.weekday()) #//0 print(myDate.isoweekday()) #//1
其中weekday方法范围为[0, 6],isoweekday方法范围为[1, 7],根据需求使用即可。
获取今天的日期
today = datetime.date.today()
快速获取今天对应的date对象。
改变date对象的日期
newDate = myDate.replace(day = 23)
可以通过replace方法改变date对象的日期,得到一个新的date对象。
时间戳转date对象
newDate = datetime.date.fromtimestamp(time.time())
上面的写法等价于datetime.date.today()
。
date对象转time.struct_time
myTime = myDate.timetuple()
这样date对象就可以很方便地与time库进行转换,这一方法等价于以下形式
yday = myDate.toordinal() - datetime.date(myDate.year, 1, 1).toordinal() + 1 #本年的天序号
time.struct_time((myDate.year, myDate.month, myDate.day, 0, 0, 0, myDate.weekday(), yday, -1))
其中的toordinal()
方法,意思是求该天的格里高利历天序号(从公元元年1月1日算第几天),反向方法datetime.date.fromordinal(x)
则是根据天序号,求该天对应的date对象。
date对象转格里高利历对象
date对象是由年、月、日定义的,而格里高利历对象则是由年、一年中的第几个星期、一星期中的第几天组成,用星期取代月份的定义。
date对象可以很方便地转换成格里高利历对象
glglDate = myDate.isocalendar()
但由于每年的第一天不一定是星期一,所以定义一年中第一个包含星期四的星期为第一个星期。
date(2003, 12, 29).isocalendar() #//datetime.IsoCalendarDate(year=2004, week=1, weekday=1) date(2004, 1, 4).isocalendar() #//datetime.IsoCalendarDate(year=2004, week=1, weekday=7)
由于这个原因,因此格里高利历纪年方式使用并不多,只做了解即可。
date对象简单格式化
print(myDate.isoformat()) #//2020-02-10
可以把date对象简单格式化为ISO 8601形式,即YYYY-MM-DD,一般使用足够了。
也可以通过str(myDate)
方式格式化,实际调用的也是isoformat方法。
简单格式字符串转date对象
newData = datetime.date.fromisoformat("2022-11-01")
显然,fromisoformat
方法就是isoformat
方法的反向运算。
date对象自定义格式化
myDate.strftime("%b %d %Y") #//Feb 10 2020
格式参数和time.strftime
方法的格式参数几乎一致,只多了个毫秒参数
- %f 毫秒,例如000123
也可以通过myDate.__format__()
方式调用,格式和参数一致。
如果要将格式化字符串转成date对象,可以使用datetime.datetime.strptime
方法,使用方法和time.strptime
方法一致。
datetime.time类
time类表示一天中的时间,该时间独立于任何特定日期。
time对象的构造方式
myTime = datetime.time(2, 20, 45, 1100)
4个参数依次代表时、分、秒、毫秒,也可以通过内置属性来获取对应的时间单位。
print(myTime.hour, myTime.minute, myTime.second, myTime.microsecond) #//2 20 45 1100
两个time对象可以比较大小,但不能进行相减运算。
通过datetime.time.min
和datetime.time.max
可以获取到时间的最小值(00:00:00)与最大值(23:59:59.999999)。
time对象替换时间
newTime = myTime.replace(hour=5)
与date对象类似,time对象也可以通过replace方法改变time对象的日期,得到一个新的time对象。
time对象的简单格式化
print(myTime.isoformat()) #//02:20:45.001100
与date对象类似,time对象也可以格式化为ISO 8601形式,即HH:MM:SS.mmmmmm。
也可以通过str(myTime)
方式格式化,实际调用的也是isoformat方法。
简单格式字符串转time对象
datetime.time.fromisoformat("04:23:33")
与date对象类似,ISO 8601形式的字符串也可以转换为time对象。
time对象自定义格式化
myTime.strftime("%H %M %S") #//02 20 45
time对象的自定义格式化,也可以通过myTime.__format__()
方式调用,格式参数和date对象完全一致,不再赘述。
datetime.datetime类
datetime对象是包含来自date对象和time对象的所有信息的单一对象,因此包括了date对象和time对象的内置属性和方法。
datetime对象的构造方式
myDatetime = datetime.datetime(2022, 6, 19, 15, 23, 32, 0)
参数依次为年、月、日、时、分、秒、毫秒,可以通过内置属性来获取对应的时间单位。
datetime对象可以比较大小,并可以进行相减运算,得到一个时间段(timedelta对象),反过来datetime对象可以和时间段进行加减运算得到一个新的datetime对象。
通过date对象和time对象组装datetime对象
myDatetime = datetime.datetime.combine(myDate, myTime)
datetime对象拆分成date对象和time对象
myDate = myDatetime.date() myTime = myDatetime.time()
准确来说,这并不是拆分,而是新建了具有相同时间参数的对象。
获取当前时区的时间
datetime.datetime.today() #或者datetime.datetime.now()
如果需要获取格林威治时间,可以使用datetime.datetime.utcnow
方法。
时间戳转datetime对象
datetime.datetime.fromtimestamp(time.time())
和date对象的时间戳转换方法一致,如果需要转成格林威治时间,可以使用datetime.datetime.utcfromtimestamp
方法。
datetime对象转时间戳
myTimeStamp = myDatetime.timestamp()
datetime对象转time.struct_time时间结构体
myTime = myDatetime.timetuple()
如果需要格林威治时间的话,可以使用myDatetime.utctimetuple
方法。
借助这三个方法,就可以实现time库和datetime库之间的自由转换,方便对时间进行处理。
datetime对象替换时间
newDatetime = myDatetime.replace(year=2025)
与date对象和time对象的使用一致。
获取该日为星期几
print(myDatetime.weekday()) #//0 print(myDatetime.isoweekday()) #//1
其中weekday方法范围为[0, 6],isoweekday方法范围为[1, 7],与date对象的方法一致。
格里高利历相关方法
# 获取格里高利历日序号 print(myDatetime.toordinal()) #//738325 # 通过格里高利历日序号得到datetime对象 newDatetime = datetime.datetime.fromordinal(738325) # datetime对象转格里高利历对象 calTime = myDatetime.isocalendar()
datetime对象的简单格式化
print(myDatetime.isoformat()) #//2022-06-19T02:20:45.001100
可以把date对象简单格式化为ISO 8601形式,很多数据库的时间数据都是这个格式存储的。
也可以通过str(myDatetime)
方式格式化,实际调用的也是isoformat方法。
简单格式字符串转datetime对象
newDatetime = datetime.datetime.fromisoformat("2011-11-04T00:05:23")
以下几种形式都符合ISO 8601形式,可以正常识别。
- 2011-11-04
- 2011-11-04T00:05:23
- 2011-11-04 00:05:23.283
- 2011-11-04 00:05:23.283+00:00
- 2011-11-04T00:05:23+04:00
datetime对象的自定义格式化
myDatetime.strftime("%Y-%m-%d %H:%M:%S")
与date对象和time对象的自定义格式化完全一致,也可以通过myDatetime.__format__()
方式调用。
格式化字符串转datetime对象
datetime.datetime.strptime("2022-06-19 02:20:45", "%Y-%m-%d %H:%M:%S")
和time.strptime
方法一致。
datetime.timedelta类
timedelta类定义了一个时间范围,表示两个date或者datetime的时间间隔,用于实现时间的相减操作。
timedelta对象的构造方式
myTimedelta = datetime.timedelta(days=1.5, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
所有参数都是可选的并且默认为 0。
相比于date、time、datetime对象构造时严格要求参数为正整数并且需要在规定范围内,timedelta的这些参数则可以是整数或者浮点数,甚至可以是负数。
例如当输入days=1.5
时,会自动转换成days=1,hours=12
。
因为这个特性,timedelta对象之间可以很方便地进行大小比较和加减乘(乘以数值)除运算,以及和date对象、datetime对象之间的加减法,并可以通过str(timedelta)
获取格式化的字符串。
可以说timedelta对象是时间运算的核心。
计算timedelta对象的总时长
既然是时间段,当然可以计算时长,可以通过total_seconds()方法获取时间段内的秒数。
print(myTimedelta.total_seconds()) #//129600.0
总结
time库和datetime库算是Python中比较基础的模块了,今天把其中比较常用的功能整理了一下,也发现了很多新的使用技巧。
另外关于时区的处理,由于目前并未有相关的使用需求,就不细究了,以后有机会再补充。
真正的幸福不应该是绝对没有不良的情绪,
而是经得起困难和挫折的考验。
《幸福的方法》
——泰勒·本-沙哈尔
评论
869076 726866It is rare knowledgeable folks within this subject, nevertheless, you seem like theres a lot more youre talking about! Thanks 538872