一、缘起
我们编写Python程序,可能会处理跟时间有关的问题,比如比较代码的执行时间,获取文件的时间属性,等等。为此,我们需要了解标准库time的用法。
二、环境
Win7中文旗舰版64位 + Python 3.64 64位 + 8G RAM
三、术语解释
在Python中,跟时间有关的一个时间术语是“Epoch Time”,中文名称叫“新纪元时间”,它是一个特定的时间点,表示1970年1月1日0时0分0秒。另外一个概念是“timestamp”,中文名称叫“时间戳”,这是指从新纪元时间到某一时刻经历的秒数。
显然,人记忆时间戳的本领并不太强,人更愿意去记住某年某月某日几时几分几秒这样的时刻。在Python中,time对象有一个类叫“struct_time”,其本质是一个存放年月日时分秒等信息的九元组,它包含9个数字元素,因为它的每个元素都有名字,所以这种元组被称为具名元组。比如,2019年6月7日17点50分38秒这个时间用time.struct_time来表示就是:
time.struct_time(tm_year=2019, tm_mon=6, tm_mday=7,
tm_hour=9, tm_min=50, tm_sec=38,
tm_wday=4, tm_yday=158, tm_isdst=0)
其中,
tm_year、tm_mon、tm_mday分别表示年、月、日,
tm_hour、tm_min、tm_sec分别表示时、分、秒,
tm_wday表示这一天是一星期的第几天(0表示星期一、1表示星期二、……),
tm_yday表示这一天是一年中的第几天(当年的1月1日是第1天,……),
tm_isdst表示当前日期时间是否夏令时时间,1表示是夏令时,0表示不是,-1表示不确定
对于Python来说,处理struct_time类比较方便,但人看起仍然费劲,人更喜欢看到类似"2019-06-07 17:50:38"这样的字符串。
在Python中,经常需要在时间戳、具名元组、日期时间字符串之间来回转换。下面看一下time库的函数。
使用标准库time,需要首先导入该库吗,导入语句如下:
import time
四、函数介绍
ctime(timestamp)
返回一个时间戳对应的日期时间字符串。例如:
'Fri Jun 7 17:48:22 2019'
gmtime([timestamp])
返回一个时间戳对应的格林尼治时间所对应的具名元组。例如:
time.struct_time(tm_year=2019, tm_mon=6, tm_mday=7,
tm_hour=9, tm_min=50, tm_sec=38,
tm_wday=4, tm_yday=158, tm_isdst=0)
如果省略时间戳参数,默认是当前时刻的时间戳。
localtime([timestamp])
返回一个时间戳对应的当地时间所对应的具名元组。例如:
time.struct_time(tm_year=2019, tm_mon=6, tm_mday=7,
tm_hour=17, tm_min=50, tm_sec=38,
tm_wday=4, tm_yday=158, tm_isdst=0)
如果省略时间戳参数,默认是当前时刻的时间戳。
注意,同一时间戳对应的格林尼治时间和当地时间因时区可能不同而略有所差别。
mktime(tuple)
把包含日期时间的具名元组转换为时间戳。
sleep(seconds)
让程序等待指定的秒数再继续执行。
strftime(format[, tuple])
把具名元组转换成指定格式的字符串。
如果省略具名元组,则默认是当前时刻对应的具名元组。例如:
>>> time.strftime("%Y-%m-%d %H:%M:%S")
'2019-06-07 18:31:38'
格式串当中主要符号的含义如下:
%Y 四位数的年份
%y 两位数的年份
%m 两位数的月份,取值区间[01,12]
%d 两位数的日期编号,取值区间[01,31]
%H 24小时制的小时数,取值区间[00,23]
%I 12小时制的小时数,取值区间[00,11]
%p 显示当地时间是AM还是PM,一般跟%I配合使用
%M 分钟数,取值区间[00,59]
%S 秒数,取值区间[00,61],60是为了支持闰秒现象,61是因历史原因保留
%j 这一天是一年中的第几天,取值范围[001,366]
%w 这一天是一个星期的第几天,星期天得到0,星期一得到1,……
%W 这一周是一年中的第几周,取值范围[00,53]
这一年的第一个周一之前的所有日子视为第00周
%U 这一周是一年中的第几周,取值范围[00,53]
这一年的第一个周日之前的所有日子视为第00周
更多的符号及含义可参考:
https://blog.csdn.net/MuWinter/article/details/77164299
strptime(string, format)
把指定格式的字符串转换为时间元组。例如:
>>> s = '2000-01-01 00:00:01'
>>> time.strptime(s, "%Y-%m-%d %H:%M:%S")
time.struct_time(tm_year=2000, tm_mon=1, tm_mday=1,
tm_hour=0, tm_min=0, tm_sec=1,
tm_wday=5, tm_yday=1, tm_isdst=-1)
time()
返回当前时刻的时间戳,如果系统支持,返回值可以带小数。
五、应用举例
1、求程序代码的运行时间
>>> import time
>>> t1 = time.time()
>>> for i in range(1000000):
i = i
>>> t2 = time.time()
>>> t2-t1
27.114551067352295
2、求文件的创建时间、访问时间、修改时间

注意,获取文件的创建时间、访问时间和修改时间也可以用如下的方法获取:
os.stat(fn).st_ctime
os.stat(fn).st_atime
os.stat(fn).st_mtime
其中fn是文件名。
3、给定合法的年月日,求这一天是一年中的第几天

4、修改文件的时间属性
文件的时间属性指文件的创建时间、修改时间和访问时间,有的时候,我们需要修改文件的这些时间属性。

上述修改文件属性的方法有一个缺点,如果要修改的日期和时间早于1970-01-02 08:00:00的话,pywintypes.Time会运行出错:
OSError: [Errno 22] Invalid argument
目前该错误暂未找到解决办法。由于该方法涉及到的技术过于底层,加上这个日期不能早于1970年的限制,因此使用的人并不多。
网上还发现了一种解决办法,是使用os.utime()方法来修改文件的访问时间和修改时间,注意该方法不能修改文件的创建时间。

解释一下上述函数:
第一个参数是文件名,第二个参数是希望修改的访问时间六元组(年月日时分秒),第三个参数是希望修改的修改时间六元组。后两个参数的默认值都是None,如果调用函数时只传递文件名参数,则将文件的访问时间和修改时间都修改为当前时间,如果后两个参数至少有一个不为None,则只修改不为None的参数对应的时间属性,值为None的参数对应的时间属性保持原状不变。
这个方法可以将文件的时间属性修改到1970年之前,缺点有两个:一是不能修改文件的创建时间,二是修改完文件的修改时间之后,在Windows的文件夹中点击详细信息浏览文件时,看不到文件的修改时间。
5、按文件的修改时间排序

六、进一步
Python还有一个datetime库,也是操作日期和时间的库,提供了更多的类和函数供我们选择。我们用os.utime()方法修改文件的时间属性时,就用了datetime库。熟悉了time对象之后,再去学习datetime库的使用就简单了。




