python标准库学习(2):time、datetime和calendar

python标准库学习(2)

标准库time、datetime和calendar

2019-09-10

python标准库中处理时间、日期的主要是time、datetime和calendar这3个库,尽管一些第三方库如dateutil、Arrow、pendulum、moment、maya、Delorean、When.py等在时间和日期处理方面扩展了很多功能,使得处理更加简洁或人性化,但标准库处理时间和日期仍然是最常见和常用的。

1. time:时间获取与转换

time库提供了近30个方法和10多个常量,是python处理时间相关的数据类型的基础。time提供的方法主要有3类:时间获取时间转换和时间相关的操作。

1.1 时间的表示方式

时间的表示方式主要有3种:

  • 时间戳(timestamp):表示从1970年1月1日0时0分0秒开始,按秒计算的时间偏移量;这里的1970年1月1日0时0分0秒被称为epoch,是时间开始的点,取决于系统平台。
  • 时间元组(struct_time):也称“结构体时间”,用一个元组表示的时间信息;
  • 时间字符串:用字符串来格式化显示时间。

以上3中表示形式在time中都有体现:

import time

time.time()           # 时间戳:1568629886.590658
time.localtime()      # 结构体时间:time.struct_time(tm_year=2019, /
                      # tm_mon=9, tm_mday=16, tm_hour=18, tm_min=31, /
                      # tm_sec=56, tm_wday=0, tm_yday=259, tm_isdst=0)
                      # 注意这个时间结构体是一个元组,不能通过类似time.localtime()['tm_min']来取值
time.ctime()          # 'Mon Sep 16 18:31:40 2019'

以下是获取时间的常用方法:

方法 作用 备注
time.time() 时间戳,返回浮点数的秒数,以epoch为起点,截止当前时间,时区为标准时间 无参数
time.time_ns() 时间戳,返回浮点数的纳秒数,以epoch为起点,截止当前时间,时区为标准时间 无参数
time.gmtime([secs]) 将时间戳转换为为单位的时间转换为标准时间下的结构体元组 参数为以秒为单位的数,默认为time.time()
time.localtime([secs]) 将时间戳转换为为单位的时间转换为系统所在时区下的结构体元组 参数为以秒为单位的数,默认为time.time()
time.ctime([secs]) 返回的时间转换为表示本地时间的字符串,以epoch为起点,截止当前时间 参数为以秒为单位的数,默认为time.time()

在结构体时间中,一般会返回一个包含8个元素的struct_time对象,这个元组可以通过位置索引(index)访问:

索引 属性 含义
0 tm_year (例如,1993) 年份
1 tm_mon range [1, 12] 月份
2 tm_mday range [1, 31] 当月第几天
3 tm_hour range [0, 23] 当日第几小时
4 tm_min range [0, 59]
5 tm_sec range [0, 61]
6 tm_wday range [0, 6] ,周一为 0 周几
7 tm_yday range [1, 366] 当年的第几天
8 tm_isdst 0, 1 或 -1 是否是夏令时
1.2 不同时间表示之间的转换

python标准库学习(2):time、datetime和calendar_第1张图片

先来看时间戳的两种转化形式:

import time

sect = 1229711247
time.ctime(sect)      # 'Sat Dec 20 02:27:27 2008'
time.gmtime(sect)     # time.struct_time(tm_year=2008, tm_mon=12, /
                      # tm_mday=19, tm_hour=18, tm_min=27, tm_sec=27, /
                      # tm_wday=4, tm_yday=354, tm_isdst=0)

strptimestrftime实现了字符串和时间元组之间的相互转换,由于涉及将时间元组转化为一定格式的时间字符串,因此需要指定format格式,一般用%加一个字母来表示一个时间字段(文档中称为directive,“指令”):

指令 含义
%a 本地化的缩写星期中每日的名称
%A 本地化的星期中每日的完整名称
%b 本地化的月缩写名称
%B 本地化的月完整名称
%c 本地化的适当日期和时间表示
%d 十进制数 [01,31] 表示的月中日。
%H 十进制数 [00,23] 表示的小时(24小时制)。
%I 十进制数 [01,12] 表示的小时(12小时制)。
%j 十进制数 [001,366] 表示的年中日。
%m 十进制数 [01,12] 表示的月。
%M 十进制数 [00,59] 表示的分钟。
%p 本地化的 AM 或 PM 。
%S 十进制数 [00,61] 表示的秒。
%U 十进制数 [00,53] 表示的一年中的周数(星期日作为一周的第一天)
%w 十进制数 [0(星期日),6] 表示的周中日。
%W 十进制数 [00,53] 表示的一年中的周数(星期一作为一周的第一天)。
%x 本地化的适当日期表示。
%X 本地化的适当时间表示。
%y 十进制数 [00,99] 表示的没有世纪的年份。
%Y 十进制数表示的带世纪的年份。
%z 时区偏移以格式
%Z 时区名称(如果不存在时区,则不包含字符)。
%% 字面的 ‘%’ 字符。

以下示例说明,字符串和时间元组之间的转换可以非常灵活:

import time

# 将字符串转化为时间元组
dt = '2018-12-31'
ts = time.strptime(dt, '%Y-%m-%d')
print(ts) # time.struct_time(tm_year=2018, /
          # tm_mon=12, tm_mday=31, tm_hour=0, tm_min=0, tm_sec=0, /
          # tm_wday=0, tm_yday=365, tm_isdst=-1)

# 将时间元组转化为字符串
tm = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
print(tm)   # '2019-09-17 19:41:02'
1.3 time模块中的其他函数

除时间获取和转换外,time另外还有2个方面的功能:使程序暂停指定时间和计算程序运行时间。
暂停指定时间用time.sleep(secs)方法,根据文档,“暂停执行调用线程达到给定的秒数。参数可以是浮点数,以指示更精确的睡眠时间。实际的暂停时间可能小于请求的时间,因为任何捕获的信号将在执行该信号的捕获例程后终止sleep()。此外,由于系统中其他活动的安排,暂停时间可能比请求的时间长任意量。”
计算程序运行时间方面,python标准库中提供了timeit,这个库可以用命令行方式和调用方法的方式计算程序运行时间。time中主要可以通过3个方法来测量程序运行时间:

函数 说明
time.time() 返回epoch为起点的系统时间的秒数,依赖于系统平台
time.perf_counter() 返回一个CPU级别的精确的秒数。包括睡眠期间经过的时间,并且是系统范围的。返回值的参考点未定义,因此只有连续调用结果之间的差异才有效
time.process_time() 返回当前进程的系统和用户CPU时间总和的值(以小数秒为单位)。它不包括睡眠期间经过的时间。根据定义,它在整个进程范围中。返回值的参考点未定义,因此只有连续调用结果之间的差异才有效

以上3个方法返回的单位都是秒,对应地有3个带_ns返回以纳秒为单位的数字:time_ns()perf_counter_ns()process_time_ns()。以下用一个例子来说明计时功能的实现,以及这些方法的不同:

def fibonacci(n):
    a, b = 0, 1
    while n > 0:
        a, b = b, a + b
        n -= 1
        yield a

a_point_tm = time.time()
a_point_perf = time.perf_counter()
a_point_proc = time.process_time()
result_u = sum([i for i in fibonacci(300)])
time.sleep(10)
result_s = sum([i for i in fibonacci(20)])
print(result_s + result_u)
b_point_tm = time.time()
b_point_perf = time.perf_counter()
b_point_proc = time.process_time()
print('time()计算结果:',b_point_tm-a_point_tm)
print('perf_counter()计算结果:',b_point_perf-a_point_perf)
print('process_time()计算结果:',b_point_proc-a_point_proc)
'''
time()计算结果: 10.003293991088867
perf_counter()计算结果: 10.002807212000334
process_time()计算结果: 0.0
'''
2. datetime:基本的日期和时间类型

datetime提供了几种操作日期和时间的数据类型,主要有timedatedatetimetimedeltatzinfotimezone等6种数据类型;最后的两个tzinfotimezone和时区有关(tzinfo定义了时区信息的基类),以下内容暂不涉及。
datetime中,既包含了time中的数据类型(对应于datetime.datetime),时间精度是到毫秒级(1 毫秒 = 0.001 秒,而不是ns纳秒级),也有date数据类型,时间单位到天,和表示一天内某个时间的timedatetime库对time库最主要的扩展体现在表示时间差(时间间隔)的timedelta类型,使得时间之间可以进行各种运算。

2.1 datetime.timedelta

文档中的完整形式是:class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0),所有的参数都是可选的并且默认值为 0。这些参数可以是整数或者浮点数,也可以是正数或者负数。timedelta中只会储存days, seconds, microseconds这3个单位,其余参数都是用这3个基本的单位转化的。
timedelta对象支持本身类型的对象,以及datedatetime类型对象的计算(datedatetime类型对象之间进行计算,返回的就是一个timedelta对象)。支持的计算类型如下表:

运算 结果
t1 = t2 + t3 t2 和 t3 的和
t1 = t2 - t3 t2 减 t3 的差
t1 = t2 * i 或 t1 = i * t2 乘以一个整数
t1 = t2 * f 或 t1 = f * t2 乘以一个浮点数,结果会被舍入到 timedelta 最接近的整数倍。
f = t2 / t3 总时间 t2 除以间隔单位 t3。 返回一个 float 对象。
t1 = t2 / f 或 t1 = t2 / i 除以一个浮点数或整数。 结果会被舍入到 timedelta 最接近的整数倍。 精度使用四舍五偶入奇不入规则。
t1 = t2 // i or t1 = t2 // t3 取整除,余数部分(如果有的话)将被丢弃
t1 = t2 % t3 余数为一个 timedelta 对象
q, r = divmod(t1, t2) 通过 : q = t1 // t2 (3) and r = t1 % t2 计算出商和余数。q是一个整数,r是一个 timedelta 对象
+t1 返回一个相同数值的 timedelta 对象。
-t1 等价于 timedelta(-t1.days, -t1.seconds, -t1.microseconds), 和 t1* -1. (1)(4)
abs(t) 当 t.days >= 0`时等于 +t, 当t.days < 0 时 -t
str(t) 返回一个形如 [D day[s], ][H]H:MM:SS[.UUUUUU] 的字符串,当 t 为负数的时候, D 也为负数
repr(t) 返回一个 timedelta 对象的字符串表示形式,作为附带正规属性值的构造器调用

以计算前一天为例,可以用当天时间直接减去一个timedelta对象就行(注意timedelta实例化时,其中的参数都是带“s”的,如days):

import datetime

td = datetime.datetime.now()           # datetime.datetime(2019, 9, 26, 21, 58, 21, 151638)
ys = td - datetime.timedelta(days=1)   # datetime.datetime(2019, 9, 25, 21, 57, 46, 737021)
ys_p = ys.strftime('%Y-%m-%d %H:%M:%S')   # '2019-09-25 22:03:23'

两个时间对象计算后,得到的结果也是timedelta

import datetime

td = datetime.datetime.now()           # datetime.datetime(2019, 9, 26, 21, 58, 21, 151638)
bth = datetime.datetime(2019,1,11, 15, 10, 40, 96)
result = td - bth           # datetime.timedelta(days=258, seconds=25307, microseconds=701024)

timedelta有一个实例方法timedelta.total_seconds(),返回时间间隔包含了多少秒。

td = datetime.datetime.today()
yd = datetime.datetime(2010,10,31)
dlt = td - yd
print(dlt.total_seconds())     # 282050531.447931
2.2 datetime中的几种数据类型
2.2.1 datetime.date

datetime.date包含3个实例属性:year, month, day;以及3个类属性:date.min(date(MINYEAR, 1, 1))、date.max(date(MAXYEAR, 12, 31))和date.resolution(两个日期对象的最小间隔,timedelta(days=1)),返回的格式为year-month-day;datetime.date类有5种构造方式,最基本的构造函数是__new__(year, month, day)

import datetime
import time

td = datetime.date(2019, 9, 18)
print(td)       # 2019-09-18
tdr = datetime.date.today()
print(tdr)      # 2019-09-18
td_ts = datetime.date.fromtimestamp(time.time())
print(td_ts)    # 2019-09-18
td_d = datetime.date.fromordinal(737320)   # 传入一个正整数n,为自公元元年1月1日开始的第n天,例如1为公元1年1月1日
print(td_d)     # 2019-09-18
td_iso = datetime.date.fromisoformat('2019-09-18')
print(td_iso)   # 2019-09-18

当构造了一个datetime.date对象后,这个对象就有了year, month, day这3个实例属性,可以通过对象.year类似的形式访问(也可以通过对象.__getattribute__('year')来实现)。
datetime.date对象的实例方法主要有3类:日期参数替换、日期表示、日期的日历信息。日期参数替换的方法是date.replace(year=self.year, month=self.month, day=self.day),这个方法可以用来替换实例属性中的值:

td = datetime.date.today()    # datetime.date(2019, 10, 8)
rd = td.replace(year=2018, day=1)
print(rd)                     # 2018-10-01,返回的对象仍是datetime.date类型

日期的表示和日历信息相关的实例方法,可以与前面构造方法的部分对比来看,例如isoformat()可以看做是fromisoformat()的对用函数,toordinal()是fromordinal()的对应函数等。
日期表示的方法主要有时间元组和字符串两种,表示为时间元组的是date.timetuple(),返回的是与time.localtime()相同类型的结构体时间(时间元组):

std = datetime.date(2018, 10, 11)
print(std.timetuple())
# time.struct_time(tm_year=2018, tm_mon=10, tm_mday=11, 
# tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=284, tm_isdst=-1)

日期的字符串表示,可以使用date.isoformat()(或date.__str__())表示为标准的字符串形式,以及date.ctime()表示为代表日期的字符串,还包括使用date.strftime(format)(或date.__format__(format)),这三种表示方式可以参看以下示例:

rd = datetime.date(2018, 5, 23)
print(rd.isoformat())    # 2018-05-23
print(str(rd))           # 2018-05-23
print(rd.ctime())        # Wed May 23 00:00:00 2018
print(rd.strftime('%Y_%m_%d'))     # 2018_05_23
print(rd.__format__('%Y-%m-%d'))   # 2018-05-23

日期的日历信息,主要包括日期的星期信息,日历位置信息,和格列高利历序号(即以公元1年1月1日为第1天的序号)。星期信息有两种表示方式:date.weekday()date.isoweekday(),区别是weekday()中星期一用“0”表示(周日是“6”),isoweekday()中星期一用“1”表示(周日是“7”),返回的是数字(int)。

rd = datetime.date(2018, 5, 23)
print(rd.weekday())      # 2
print(rd.isoweekday())   # 3

date.isocalendar()返回一个三元组:(ISO year, ISO week number, ISO weekday) ,其中ISO是国际标准的意思,文档中举了一个例子可以作为说明:“2004 年的第一天是一个星期四,因此 ISO 2004 年的第一个星期开始于 2003 年 12 月 29 日星期一,结束于 2004 年 1 月 4 日星期日,因此
date(2003, 12, 29).isocalendar() == (2004, 1, 1) and date(2004, 1, 4).isocalendar() == (2004, 1, 7)

rd = datetime.date(2018, 5, 23)
print(rd.isocalendar())    # (2018, 21, 3)

除此之外,datetime.date也支持比较运算(类似地,以下提到的datetime.timedatetime.datetime也支持):

lt = datetime.date(2019, 10, 9)
rt = datetime.date(2018, 10, 8)
lt > rt  # True
lt >= rt # True
lt == rt # False
2.2.2 datetime.time

datetime.time表示一天中的某个时间点(不包含日期信息),包含6个实例属性:hour、minute、second、microsecond、tzinfo和fold,最后一个fold的含义是“用于在重复的时间段中消除边界时间歧义”,取值为0或1(默认为0)。除了直接通过赋值实例化之外,datetime.time还有一个构造方法time.fromisoformat(time_string),但文档提示这个方式只是time.isoformat()的逆操作,并不能解析所有格式的ISO时间字符串。
实例方法中,除了与时区相关的操作外,与前面datetime.date类似,也有time.isoformat(timespec='auto')time.strftime(format)time.replace(hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, * fold=0)方法,详见文档。

2.2.3 datetime.datetime

datetime.time是包含了datetime.datedatetime.time所有信息的数据类型,包含9个实例属性:year、month、day、hour、minute、second、microsecond、tzinfo和fold。
datetime.datetime数据类型的实例化(构造方法)有很多:

import time
import datetime

# 传入参数进行构造
td = datetime.datetime(2019, 10, 8)  # datetime.datetime(2019, 10, 8, 0, 0)

# 表示当前时间,带utc的为标准时间,其余为本地时间
td = datetime.datetime.today()       # datetime.datetime(2019, 10, 8, 15, 17, 11, 410101)
td = datetime.datetime.now()         # datetime.datetime(2019, 10, 8, 15, 17, 11, 410101)
td = datetime.datetime.utcnow()      # datetime.datetime(2019, 10, 8, 7, 18, 44, 10496)

# 传入时间戳,带utc的为标准时间,其余为本地时间
td = datetime.datetime.fromtimestamp(time.time())      # datetime.datetime(2019, 10, 8, 15, 20, 36, 362426)
td = datetime.datetime.utcfromtimestamp(time.time())   # datetime.datetime(2019, 10, 8, 7, 22, 5, 428847)

# 传入格列高利历序号(即公元1年1月1日起的第几天)
td = datetime.datetime.fromordinal(737340)     # datetime.datetime(2019, 10, 8, 0, 0)

# 传入标准的时间字符串
td = datetime.datetime.fromisoformat('2019-10-08 15:25:23')   # datetime.datetime(2019, 10, 8, 15, 25, 23)

# 合并日期和时间的数据
td = datetime.datetime.combine(datetime.date.today(), datetime.time(12, 5, 34))    # datetime.datetime(2019, 10, 8, 12, 5, 34)fold

# 字符串序列化
td = datetime.datetime.strptime('2019-10-08 15:25:23', '%Y-%m-%d %H:%M:%S')        # datetime.datetime(2019, 10, 8, 15, 25, 23)

datetime.datetime有min、max、resolution等3个类方法,以及year、month、day、hour、minute、second、microsecond、tzinfo和fold等9个实例方法:

datetime.datetime.resolution           # datetime.timedelta(microseconds=1)
td = datetime.datetime.now()           # datetime.datetime(2019, 10, 8, 22, 35, 24, 199131)
td.day                                 # 8

datetime.datetime的实例方法主要有3类:参数替换、时间表示(以及表示方式的转换)、时间的日历信息以及时区操作等4类。
参数替换的方法是datetime.replace(year=self.year, month=self.month, day=self.day, hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, * fold=0)
时间表示的相关方法中,

  • datetime.date()datetime.time()用于将datetime.datetime对象转换为datetime.datedatetime.time类型的对象;
  • datetime.timetuple()datetime.utctimetuple()可以将datetime.datetime对象转换为时间元组格式;
  • datetime.toordinal()会返回日期的预期格列高利历序号;
  • datetime.timestamp()会返回时间戳;
  • datetime.isoformat()会返回一个标准的时间戳(ISO 8601 格式表示日期和时间的字符串 YYYY-MM-DDTHH:MM:SS.ffffff);
  • datetime.ctime()返回一个表示时间的字符串
  • datetime.strftime(format)返回一个由显式格式字符串所指明的代表日期和时间的字符串:
td = datetime.datetime.now()     # datetime.datetime(2019, 10, 8, 23, 10, 4, 243267)
td.date()                        # datetime.date(2019, 10, 8)
td.time()                        #datetime.time(23, 10, 4, 243267)
td.timetuple()   # time.struct_time(tm_year=2019, tm_mon=10, 
                 # tm_mday=8, tm_hour=23, tm_min=10, tm_sec=53, tm_wday=1, tm_yday=281, tm_isdst=-1)
td.toordinal()   # 737340
td.timestamp()   # 1570547527.534725
td.isoformat()   # '2019-10-08T23:14:17.739123'
td.ctime()       # 'Tue Oct  8 23:16:56 2019'
td.strftime('%Y-%m-%d  %H-%M-%S')    # '2019-10-08  23-19-02'

此外与datetime.date中相同,datetime.datetime也提供了关于日历信息的方法,主要有以下3个:

td = datetime.datetime.fromisoformat('2019-10-08 15:25:23') 
td.weekday()       # 1
td.isoweekday()    # 2
td.isocalendar()   # (2019, 41, 2)
3. calendar:日历相关函数

calendar定义了一些日历相关的数据类型,并基于此提供了一系列操作日期的相关函数。默认情况下,这些日历(数据类型)把星期一当作一周的第一天,星期天为一周的最后一天(按照欧洲惯例)。
calendar主要由类Calendar、Calendar一些子类(TextCalendar,HTMLCalendar以及这两个类的子类)以及一些方法构成。最基本的用法是通过calendar.calendar(year, w=2, l=1, c=6, m=3)方法来实例化一个日历:

import calendar

cld = calendar.calendar(2019)
print(cld)
'''
                                  2019

      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  5  6                   1  2  3                   1  2  3
 7  8  9 10 11 12 13       4  5  6  7  8  9 10       4  5  6  7  8  9 10
14 15 16 17 18 19 20      11 12 13 14 15 16 17      11 12 13 14 15 16 17
21 22 23 24 25 26 27      18 19 20 21 22 23 24      18 19 20 21 22 23 24
28 29 30 31               25 26 27 28               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  6  7             1  2  3  4  5                      1  2
 8  9 10 11 12 13 14       6  7  8  9 10 11 12       3  4  5  6  7  8  9
15 16 17 18 19 20 21      13 14 15 16 17 18 19      10 11 12 13 14 15 16
22 23 24 25 26 27 28      20 21 22 23 24 25 26      17 18 19 20 21 22 23
29 30                     27 28 29 30 31            24 25 26 27 28 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  6  7                1  2  3  4                         1
 8  9 10 11 12 13 14       5  6  7  8  9 10 11       2  3  4  5  6  7  8
15 16 17 18 19 20 21      12 13 14 15 16 17 18       9 10 11 12 13 14 15
22 23 24 25 26 27 28      19 20 21 22 23 24 25      16 17 18 19 20 21 22
29 30 31                  26 27 28 29 30 31         23 24 25 26 27 28 29
                                                    30

      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  5  6                   1  2  3                         1
 7  8  9 10 11 12 13       4  5  6  7  8  9 10       2  3  4  5  6  7  8
14 15 16 17 18 19 20      11 12 13 14 15 16 17       9 10 11 12 13 14 15
21 22 23 24 25 26 27      18 19 20 21 22 23 24      16 17 18 19 20 21 22
28 29 30 31               25 26 27 28 29 30         23 24 25 26 27 28 29
                                                    30 31
'''

calendar.calendar(year, w=2, l=1, c=6, m=3),根据文档的说明,是“使用 TextCalendar 类的 formatyear() 返回整年的3列的日历以多行字符串的形式”,可选参数 w, l, 和 c 分别表示日期列数, 周的行数, 和月之间的间隔。
这相当于:

cld = calendar.TextCalendar()
result = cld.formatyear(2019)
print(result)

可以通过calendar.setfirstweekday(weekday)来指定一周的开始(0表示星期一,6表示星期天):

calendar.setfirstweekday(6)
cld = calendar.calendar(2019)
print(cld)
'''
                                  2019

      January                   February                   March
Su Mo Tu We Th Fr Sa      Su Mo Tu We Th Fr Sa      Su Mo Tu We Th Fr Sa
       1  2  3  4  5                      1  2                      1  2
 6  7  8  9 10 11 12       3  4  5  6  7  8  9       3  4  5  6  7  8  9
13 14 15 16 17 18 19      10 11 12 13 14 15 16      10 11 12 13 14 15 16
20 21 22 23 24 25 26      17 18 19 20 21 22 23      17 18 19 20 21 22 23
27 28 29 30 31            24 25 26 27 28            24 25 26 27 28 29 30
                                                    31

       April                      May                       June
Su Mo Tu We Th Fr Sa      Su Mo Tu We Th Fr Sa      Su Mo Tu We Th Fr Sa
    1  2  3  4  5  6                1  2  3  4                         1
 7  8  9 10 11 12 13       5  6  7  8  9 10 11       2  3  4  5  6  7  8
14 15 16 17 18 19 20      12 13 14 15 16 17 18       9 10 11 12 13 14 15
21 22 23 24 25 26 27      19 20 21 22 23 24 25      16 17 18 19 20 21 22
28 29 30                  26 27 28 29 30 31         23 24 25 26 27 28 29
                                                    30

        July                     August                  September
Su Mo Tu We Th Fr Sa      Su Mo Tu We Th Fr Sa      Su Mo Tu We Th Fr Sa
    1  2  3  4  5  6                   1  2  3       1  2  3  4  5  6  7
 7  8  9 10 11 12 13       4  5  6  7  8  9 10       8  9 10 11 12 13 14
14 15 16 17 18 19 20      11 12 13 14 15 16 17      15 16 17 18 19 20 21
21 22 23 24 25 26 27      18 19 20 21 22 23 24      22 23 24 25 26 27 28
28 29 30 31               25 26 27 28 29 30 31      29 30

      October                   November                  December
Su Mo Tu We Th Fr Sa      Su Mo Tu We Th Fr Sa      Su Mo Tu We Th Fr Sa
       1  2  3  4  5                      1  2       1  2  3  4  5  6  7
 6  7  8  9 10 11 12       3  4  5  6  7  8  9       8  9 10 11 12 13 14
13 14 15 16 17 18 19      10 11 12 13 14 15 16      15 16 17 18 19 20 21
20 21 22 23 24 25 26      17 18 19 20 21 22 23      22 23 24 25 26 27 28
27 28 29 30 31            24 25 26 27 28 29 30      29 30 31
'''

类似地,calendar提供了calendar.monthcalendar(year, month)方法,输出某个月的日历,也可以通过calendar.prcal(year, w=0, l=0, c=6, m=3)calendar.prmonth(theyear, themonth, w=0, l=0)直接打印出日历或月历。
除了纯文本意外的另一种输出形式是html格式(默认参数可以参考之前列出的,这是一个没有边框线的月历):

cld = calendar.HTMLCalendar()
result = cld.formatmonth(2019,10)
print(result)
'''
October 2019
MonTueWedThuFriSatSun
 123456
78910111213
14151617181920
21222324252627
28293031   
'''

除以上两种显示日历的方式外,calendar还提供了一些很有用方法。calendar.isleap(year)判断这个年份是否是闰年;calendar.leapdays(y1, y2)返回两个年份之间闰年的数量:

calendar.isleap(2019)     # False
calendar.leapdays(2010,2019)   # 2

calendar.weekday(year, month, day)可以判断某个日期是星期几,返回一个数字(0代表星期一):

calendar.weekday(-101,11,2)   # 3

calendar.timegm(tuple)被文档称为“一个不相关但很好用的函数”(an unrelated but handy function),“它接收一个时间元组例如 time 模块中的 gmtime() 函数的返回并返回相应的 Unix 时间戳,假定 1970 年开始计数”,可以与time模块的time.mktime()对比:

import time
import datetime
import calendar

dy = datetime.date(2018, 11, 1)
dytuple = dy.timetuple()
res_a = calendar.timegm(dytuple)
res_b = time.mktime(dytuple)
print(res_a)     # 1541030400,这是基于标准时间的结果
print(res_b)     # 1541001600.0,这是基于本地时间的结果

你可能感兴趣的:(python学习)