>凡所行的,都不要发怨言、起争论,使你们无可指摘,诚实无伪,在这弯曲悖谬的世代作神无瑕疵的儿女。你们显在这世代中,好像明光照耀,将生命的道表明出来。(PHILIPPIANS 2:14-15)
#标准库(5)
“一寸光阴一寸金,寸金难买寸光阴”,时间是宝贵的。
在日常生活中,“时间”这个术语是比较笼统和含糊的。在物理学中,“时间”是一个非常明确的概念。在Python中,“时间”可以通过相关模块实现。
##calendar
>>> import calendar
>>> cal = calendar.month(2015, 1)
>>> print cal
January 2015
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
轻而易举得到了2015年1月的日历,并且排列的还那么整齐。这就是`calendar`模块。读者可以用`dir()`去查看这个模块下的所有内容。为了让读者阅读方便,将常用的整理如下:
**calendar(year,w=2,l=1,c=6)**
返回year年的年历,3个月一行,间隔距离为c。 每日宽度间隔为w字符。每行长度为`21* w+18+2* c`。l是每星期行数。
>>> year = calendar.calendar(2015)
>>> print year
2015
January February March
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 1 1
5 6 7 8 9 10 11 2 3 4 5 6 7 8 2 3 4 5 6 7 8
12 13 14 15 16 17 18 9 10 11 12 13 14 15 9 10 11 12 13 14 15
19 20 21 22 23 24 25 16 17 18 19 20 21 22 16 17 18 19 20 21 22
26 27 28 29 30 31 23 24 25 26 27 28 23 24 25 26 27 28 29
30 31
April May June
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 5 1 2 3 1 2 3 4 5 6 7
6 7 8 9 10 11 12 4 5 6 7 8 9 10 8 9 10 11 12 13 14
13 14 15 16 17 18 19 11 12 13 14 15 16 17 15 16 17 18 19 20 21
20 21 22 23 24 25 26 18 19 20 21 22 23 24 22 23 24 25 26 27 28
27 28 29 30 25 26 27 28 29 30 31 29 30
July August September
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 5 1 2 1 2 3 4 5 6
6 7 8 9 10 11 12 3 4 5 6 7 8 9 7 8 9 10 11 12 13
13 14 15 16 17 18 19 10 11 12 13 14 15 16 14 15 16 17 18 19 20
20 21 22 23 24 25 26 17 18 19 20 21 22 23 21 22 23 24 25 26 27
27 28 29 30 31 24 25 26 27 28 29 30 28 29 30
31
October November December
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 1 1 2 3 4 5 6
5 6 7 8 9 10 11 2 3 4 5 6 7 8 7 8 9 10 11 12 13
12 13 14 15 16 17 18 9 10 11 12 13 14 15 14 15 16 17 18 19 20
19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27
26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31
30
其它部分就是按照上面的样式,将2015年度的各个月份日历完全显示出来。
**isleap(year)**
判断是否为闰年,是则返回true,否则false.
>>> calendar.isleap(2000)
True
>>> calendar.isleap(2015)
False
怎么判断一年是闰年,常常见诸于一些编程语言的练习题,现在用一个方法搞定。
**leapdays(y1, y2)**
返回在y1,y2两年之间的闰年总数,包括y1,但不包括y2,这有点如同序列的切片一样。
>>> calendar.leapdays(2000, 2004)
1
>>> calendar.leapdays(2000, 2003)
1
**month(year, month, w=2, l=1)**
返回year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6,l是每星期的行数。
>>> print calendar.month(2015, 5)
May 2015
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
**monthcalendar(year,month)**
返回一个列表,列表内的元素还是列表。每个子列表代表一个星期,都是从星期一到星期日,如果没有本月的日期,则为0。
>>> calendar.monthcalendar(2015, 5)
[[0, 0, 0, 0, 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]]
读者可以将这个结果和`calendar.month(2015, 5)`去对照理解。
**monthrange(year, month)**
返回一个元组,里面有两个整数。第一个整数代表着该月的第一天从星期几是(从0开始,依次为星期一、星期二,直到6代表星期日)。第二个整数是该月一共多少天。
>>> calendar.monthrange(2015, 5)
(4, 31)
从返回值可知,2015年5月1日是星期五,这个月一共31天。这个结果,也可以从日历中看到。
**weekday(year,month,day)**
输入年月日,知道该日是星期几(注意,返回值依然按照从0到6依次对应星期一到星期六)。
>>> calendar.weekday(2015, 5, 4) #星期一
0
>>> calendar.weekday(2015, 6, 4) #星期四
3
##time
**time()**
`time`模块很常用,比如记录某个程序运行时间的长短等,下面一一道来其中的方法。
- `time()`
>>> import time
>>> time.time()
1430745298.391026
`time.time()`获得的是当前时间(严格说是时间戳),只不过这个时间对人不友好,它是以1970年1月1日0时0分0秒为计时起点,到当前的时间长度(不考虑闰秒)。
>UNIX時間,或稱POSIX時間是UNIX或類UNIX系統使用的時間表示方式:從協調世界時1970年1月1日0時0分0秒起至現在的總秒數,不考慮閏秒
>現時大部分使用UNIX的系統都是32位元的,即它們會以32位二進制數字表示時間。但是它們最多只能表示至協調世界時間2038年1月19日3時14分07秒(二進制:01111111 11111111 11111111 11111111,0x7FFF:FFFF),在下一秒二進制數字會是10000000 00000000 00000000 00000000,(0x8000:0000),這是負數,因此各系統會把時間誤解作1901年12月13日20時45分52秒(亦有說回歸到1970年)。這時可能會令軟體發生問題,導致系統癱瘓。
>目前的解決方案是把系統由32位元轉為64位元系統。在64位系統下,此時間最多可以表示到292,277,026,596年12月4日15時30分08秒。
有没有对人友好一点的时间显示呢?
**localtime()**
>>> time.localtime()
time.struct_time(tm_year=2015, tm_mon=5, tm_mday=4, tm_hour=21, tm_min=33, tm_sec=39, tm_wday=0, tm_yday=124, tm_isdst=0)
这个就友好多了。得到的结果可以称之为时间元组(也有括号),其各项的含义是:
|索引| 属性 |含义|
|----|----------|----|
|0 |tm_year| 年|
|1 |tm_mon| 月|
|2| tm_mday |日|
|3| tm_hour| 时|
|4| tm_min| 分|
|5| tm_sec| 秒|
|6| tm_wday| 一周中的第几天|
|7| tm_yday| 一年中的第几天|
|8| tm_isdst| 夏令时|
>>> t = time.localtime()
>>> t[1]
5
通过索引能够得到相应的属性,上面的例子中就得到了当前时间的月份。
其实,`time.localtime()`不是没有参数,它在默认情况下,以`time.time()`的时间戳为参数。言外之意就是说可以自己输入一个时间戳,返回那个时间戳所对应的时间(按照公元和时分秒计时)。例如:
>>> time.localtime(100000)
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=2, tm_hour=11, tm_min=46, tm_sec=40, tm_wday=4, tm_yday=2, tm_isdst=0)
**gmtime()**
localtime()得到的是本地时间,如果要国际化,就最好使用格林威治时间。可以这样:
>>> import time
>>> time.gmtime()
time.struct_time(tm_year=2015, tm_mon=5, tm_mday=4, tm_hour=23, tm_min=46, tm_sec=34, tm_wday=0, tm_yday=124, tm_isdst=0)
>格林威治標準時間(中國大陸翻譯:格林尼治平均時間或格林尼治標準時間,台、港、澳翻譯:格林威治標準時間;英语:Greenwich Mean Time,GMT)是指位於英國倫敦郊區的皇家格林威治天文台的標準時間,因為本初子午線被定義在通過那裡的經線。
还有更友好的,请继续阅读。
**asctime()**
>>> time.asctime()
'Mon May 4 21:46:13 2015'
`time.asctime()`的参数为空时,默认是以`time.localtime()`的值为参数,所以得到的是当前日期时间和星期。当然,也可以自己设置参数:
>>> h = time.localtime(1000000)
>>> h
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=12, tm_hour=21, tm_min=46, tm_sec=40, tm_wday=0, tm_yday=12, tm_isdst=0)
>>> time.asctime(h)
'Mon Jan 12 21:46:40 1970'
注意,`time.asctime()`的参数必须是时间元组,类似上面那种。不是时间戳,通过`time.time()`得到的时间戳也可以转化为上面形式。
**ctime()**
>>> time.ctime()
'Mon May 4 21:52:22 2015'
在没有参数的时候,事实上是以`time.time()`的时间戳为参数。也可以自定义一个时间戳。
>>> time.ctime(1000000)
'Mon Jan 12 21:46:40 1970'
跟前面得到的结果是一样的,只不过用了时间戳作为参数。
在前述函数中,通过`localtime()`、`gmtime()`得到的是时间元组,通过`time()`得到的是时间戳。有的函数如`asctime()`是以时间元组为参数,有的如`ctime()`是以时间戳为参数,这样做的目的是为了满足编程中多样化的需要。
**mktime()**
mktime()也是以时间元组为参数,但是它返回的不是可读性更好的那种样式,而是:
>>> lt = time.localtime()
>>> lt
time.struct_time(tm_year=2015, tm_mon=5, tm_mday=5, tm_hour=7, tm_min=55, tm_sec=29, tm_wday=1, tm_yday=125, tm_isdst=0)
>>> time.mktime(lt)
1430783729.0
返回了时间戳。就类似于`localtime()`的逆过程(`localtime()`是以时间戳为参数)。
好像还缺点什么,因为在编程中,用的比较多的是“字符串”,似乎还没有将时间转化为字符串的函数。这个应该有。
**strftime()**
函数格式稍微复杂一些。
Help on built-in function strftime in module time:
strftime(...)
strftime(format[, tuple]) -> string
Convert a time tuple to a string according to a format specification.
See the library reference manual for formatting codes. When the time tuple
is not present, current time as returned by localtime() is used.
将时间元组按照指定格式要求转化为字符串。如果不指定时间元组,就默认为`localtime()`值。说复杂,是在于其format,需要用到下面的东西。
| 格式| 含义| 取值范围(格式)|
|------|-------|-------------------|
|%y |去掉世纪的年份 |00-99,如"15"|
|%Y |完整的年份| 如"2015" |
|%j |指定日期是一年中的第几天| 001-366|
| %m| 返回月份| 01-12|
|%b| 本地简化月份的名称| 简写英文月份|
|%B| 本地完整月份的名称| 完整英文月份|
|%d| 该月的第几日| 如5月1日返回"01"|
|%H| 该日的第几时(24小时制)| 00-23|
|%l| 该日的第几时(12小时制)| 01-12|
|%M| 分钟| 00-59|
|%S| 秒 |00-59|
|%U| 在该年中的第多少星期(以周日为一周起点)| 00-53|
|%W| 同上,只不过是以周一为起点|00-53|
|%w| 一星期中的第几天 |0-6|
|%Z| 时区|在中国大陆测试,返回CST,即China Standard Time|
|%x| 日期| 日/月/年|
|%X| 时间| 时:分:秒|
|%c| 详细日期时间| 日/月/年 时:分:秒|
|%%| ‘%’字符 |‘%’字符|
|%p| 上下午| AM or PM|
简要列举如下:
>>> time.strftime("%y,%m,%d")
'15,05,05'
>>> time.strftime("%y/%m/%d")
'15/05/05'
分隔符可以自由指定。既然已经变成字符串了,就可以“随心所欲不逾矩”了。
**strptime()**
Help on built-in function strptime in module time:
strptime(...)
strptime(string, format) -> struct_time
Parse a string to a time tuple according to a format specification.
See the library reference manual for formatting codes (same as strftime()).
`strptime()`的作用是将字符串转化为时间元组。
请注意的是,其参数要指定两个,一个是时间字符串,另外一个是时间字符串所对应的格式,格式符号用上表中的。例如:
>>> today = time.strftime("%y/%m/%d")
>>> today
'15/05/05'
>>> time.strptime(today, "%y/%m/%d")
time.struct_time(tm_year=2015, tm_mon=5, tm_mday=5, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, tm_yday=125, tm_isdst=-1)
##datetime
虽然`time`模块已经能够把有关时间方面的东西搞定了,但是,有时调用起来感觉不是很直接,于是又出来了一个`datetime`模块,供程序猿和程序媛们选择使用。
`datetime`模块中有几个类:
- datetime.date:日期类,常用的属性有year/month/day
- datetime.time:时间类,常用的有hour/minute/second/microsecond
- datetime.datetime:日期时间类
- datetime.timedelta:时间间隔,即两个时间点之间的时间长度
- datetime.tzinfo:时区类
###`date`类
通过实例了解常用的属性:
>>> import datetime
>>> today = datetime.date.today()
>>> today
datetime.date(2015, 5, 5)
其实这里生成了一个日期对象,然后操作这个对象的各种属性。可以用`print`,以获得更佳视觉:
>>> print today #Python 3: print(today)
2015-05-05
>>> print today.ctime() #Python 3: print(today.ctime())
Tue May 5 00:00:00 2015
>>> print today.timetuple() #Python 3: print(today.timetuple())
time.struct_time(tm_year=2015, tm_mon=5, tm_mday=5, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, tm_yday=125, tm_isdst=-1)
>>> print today.toordinal() #Python 3: print(today.toordinal())
735723
特别注意,如果你妄图用`datetime.date.year()`,是会报错的,因为year不是一个方法,必须这样行:
>>> print today.year
2015
>>> print today.month
5
>>> print today.day
5
进一步看看时间戳与格式化时间格式的转换
>>> to = today.toordinal()
>>> to
735723
>>> print datetime.date.fromordinal(to)
2015-05-05
>>> import time
>>> t = time.time()
>>> t
1430787994.80093
>>> print datetime.date.fromtimestamp(t)
2015-05-05
还可以更灵活一些,修改日期。
>>> d1 = datetime.date(2015,5,1)
>>> print d1
2015-05-01
>>> d2 = d1.replace(year=2005, day=5)
>>> print d2
2005-05-05
###time类
也要生成time对象
>>> t = datetime.time(1,2,3)
>>> print t
01:02:03
它的常用属性:
>>> print t.hour
1
>>> print t.minute
2
>>> print t.second
3
>>> t.microsecond
0
>>> print t.tzinfo
None
###timedelta类
主要用来做时间的运算。比如:
>>> now = datetime.datetime.now()
>>> print now #Python 3: print(now)
2015-05-05 09:22:43.142520
没有讲述`datetime`类,因为在有了date和time类知识之后,这个类比较简单。
对`now`增加5个小时;
>>> b = now + datetime.timedelta(hours=5)
>>> print b #Python 3: print(b)
2015-05-05 14:22:43.142520
增加两周;
>>> c = now + datetime.timedelta(weeks=2)
>>> print c #Python 3: print(c)
2015-05-19 09:22:43.142520
计算时间差:
>>> d = c - b
>>> print d #Python 3: print(d)
13 days, 19:00:00
------
[总目录](./index.md) | [上节:标准库(4)](./223.md) | [下节:标准库(6)](./225.md)
如果你认为有必要打赏我,请通过支付宝:**qiwsir@126.com**,不胜感激。