在学习编程过程中,我一直遵循一个简单的思路,更好的写代码,写出更好的代码,python作为我的主要开发工具,有必要深入了解下python标准库.
- 更好的利用标准库中已经有的轮子,提升自己的开发效率.
- 标准库的源码一定是最pythonic,学习其pythonic的编码风格.
该系列文章全部基于python3.5,交互式环境全都基于Ipython 5.1.0
文章采用标准库常用功能介绍,源码分析(挑选重要的),应用场景介绍(工程实践较少,见谅^^)为组织方式.
GTM/UTC和时间戳
这次介绍的是python中和时间有关的几个模块,首先明白几个关键概念.
GMT: 格林尼治标准时间,是指位于英国伦敦郊区的皇家格林尼治天文台当地的标准时间,因为本初子午线被定义为通过那里的经线.
自1924年2月5日开始,格林尼治天文台负责每隔一小时向全世界发放调时信息。
理论上来说,格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治上空最高点时)的时间。但由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能与实际的太阳时有误差,最大误差达16分钟。原因在于地球每天的自转是有些不规则的,而且正在缓慢减速,因此格林尼治时间基于天文观测本身的缺陷,已经被原子钟报时的协调世界时(UTC)所取代
UTC: 是最主要的世界时间标准,是世界上调节时钟和时间的主要标准.地球被划分为二十四个时区,每个地方都有自己的本地时间,在国际互联网无线点通信等领域,处理起时间来会很复杂,为了统一,使用一个统一时间就是UTC时间.UTC时间与GMT时间一样,都是英国当地时间.北京时区是东八区,领先UTC时间8个小时,在编程工作中主要是用到UTC时间这.常用如下形式表示:
2018-2-19 08:00:00 UTC+8:00//北京时间
2018-2-19 00:00:00 UTC+0:00//UTC时间
本地时间: 指系统设定时区的时间,例如北京时间是UTC+8:00时区的时间,而UTC时间指UTC+0:00时区的时间。
UTC + 时间差 = 本地时间
时间戳:时间戳(timestamp)是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数.是在计算机世界中用一个浮点数唯一标识一个确定的时间.可以由时间戳转化为UTC时间.
用datetime来处理时间
python内建模块datetime模块是专门用来处理时间的标准库.下面主要介绍在编程中常用UTC标准时区时间,时间戳,本地时间之间的转换.
获取当前本地时间
In [1]: import datetime
In [2]: datetime.datetime.now()
Out[2]: datetime.datetime(2018, 3, 30, 14, 7, 26, 243573)
得到的是一个python的datetime对象,并且表示的是本地时间,是指的操作系统设定的时间
获取当前时间的时间戳,也就是datetime对象转化为时间戳,调用datetime类的timestamp方法
In [3]: a = datetime.datetime.now()
In [4]: a
Out[4]: datetime.datetime(2018, 3, 30, 14, 17, 3, 299289)
In [5]: a.timestamp()
Out[5]: 1522390623.299289
时间戳没有时区概念,利用fromtimestamp方法可以将时间戳转化为本地时间,fromtimestamp默认的是转化为本地时区的datetime类型,也就是会将任何datetime时间类型按照本地时间转化为时间戳
In [6]: t = 1522390623.299289
In [7]: b = datetime.datetime.fromtimestamp(t)
In [8]: b
Out[8]: datetime.datetime(2018, 3, 30, 14, 17, 3, 299289)
可以将时间戳转化为UTC标准时区时间
In [9]: c = datetime.datetime.utcfromtimestamp(t)
In [10]: c
Out[10]: datetime.datetime(2018, 3, 30, 6, 17, 3, 299289)
可以直接获得UTC时间的python datetime类型,注意这个datetime类型不包括时区信息
In [11]: datetime.datetime.utcnow()
Out[11]: datetime.datetime(2018, 3, 30, 6, 25, 24, 319623)
datetime 类型的方法
这是python的标准时间类型,重点掌握这个强大的数据结构
最常用的是str与datetime的转化
strftime 将时间类型格式化成字符串
In [47]: now = datetime.datetime.now()
In [48]: now
Out[48]: datetime.datetime(2018, 3, 30, 15, 10, 12, 640037)
In [49]: now.strftime('%Y-%m-%d %H:%M:%S')
Out[49]: '2018-03-30 15:10:12'
In [50]: datetime.datetime.strftime(now,'%Y-%m-%d %H:%M:%S')
Out[50]: '2018-03-30 15:10:12'
In [51]: now.ctime()
Out[51]: 'Fri Mar 30 16:12:03 2018'
strptime 字符串转化成时间类型
In [55]: datetime.datetime.strptime('2018-3-10 00:00:00','%Y-%m-%d %H:%M:%S')
Out[55]: datetime.datetime(2018, 3, 10, 0, 0)
这里面涉及到了格式化时间格式时候,特殊的字母表示特殊的意义,请参照python官方文档定义时间格式
创建一个标准时间类型
In [97]: datetime.datetime(2018,3,30,16,33,44)
Out[97]: datetime.datetime(2018, 3, 30, 16, 33, 44)
可以通过datetime暴露出来的方法提取日期格式的具体时间信息
In [79]: now.year
Out[79]: 2018
In [80]: now.month
Out[80]: 3
In [81]: now.day
Out[81]: 30
In [82]: now.minute
Out[82]: 10
In [83]: now.hour
Out[83]: 15
In [84]: now.second
Out[84]: 12
In [85]: now.timetuple()
Out[85]: time.struct_time(tm_year=2018, tm_mon=3, tm_mday=30, tm_hour=15, tm_min=10, tm_sec=12, tm_wday=4, tm_yday=89, tm_isdst=-1)
可以将datetime格式拆分为date格式和time格式,并且可以将后两者再次组成为datetime格式
In [86]: now.date()
Out[86]: datetime.date(2018, 3, 30)
In [87]: now.weekday()
Out[87]: 4
In [88]: now.today()
Out[88]: datetime.datetime(2018, 3, 30, 15, 37, 50, 992386)
In [89]: now.time()
Out[89]: datetime.time(15, 10, 12, 640037)
In [90]: datetime.datetime.combine(now.date(),now.time())
Out[90]: datetime.datetime(2018, 3, 30, 15, 10, 12, 640037)
可以获得ISO 标准的日期格式
In [94]: now.isocalendar()
Out[94]: (2018, 13, 5)
In [95]: now.isoformat()
Out[95]: '2018-03-30T15:10:12.640037'
In [96]: now.isoweekday()
Out[96]: 5
timedelta 关于时间的计算
timedelta对象类似于时间段对象,表示一段时间,可以用来时间计算
传入不同的关键字参数,获得相对应的timedelta对象
class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
timedelta对象是按照天数,秒数,微秒数来显示
In [112]: datetime.timedelta(hours = 10)
Out[112]: datetime.timedelta(0, 36000)//有天数和秒数
In [113]: datetime.timedelta(days = 10)
Out[113]: datetime.timedelta(10)//只有天数
In [114]: datetime.timedelta(weeks = 10)
Out[114]: datetime.timedelta(70)
In [115]: datetime.timedelta(seconds = 10)
Out[115]: datetime.timedelta(0, 10)
In [116]: datetime.timedelta(days = 10)
Out[116]: datetime.timedelta(10)
In [117]: datetime.timedelta(microseconds = 10)
Out[117]: datetime.timedelta(0, 0, 10)//有天数秒数微秒
利用timedelta类型进行时间计算
In [121]: t1+t2+t3
Out[121]: datetime.timedelta(8, 3600)
In [122]: t2-t1
Out[122]: datetime.timedelta(6)
In [123]: t2-t1-t3
Out[123]: datetime.timedelta(5, 82800)
In [124]: (t2-t1)/t3
Out[124]: 144.0
In [125]: t1*3
Out[125]: datetime.timedelta(3)
In [126]: t1/3
Out[126]: datetime.timedelta(0, 28800)
In [127]: t2/t3
Out[127]: 168.0
In [128]: +t1
Out[128]: datetime.timedelta(1)
In [129]: -t1
Out[129]: datetime.timedelta(-1)
其实现了str方法可以用str()函数调用
In [130]: str(t1)
Out[130]: '1 day, 0:00:00'
In [131]: str(t1-t2)
Out[131]: '-6 days, 0:00:00'
In [132]: str(t2-t1-t3)
Out[132]: '5 days, 23:00:00'
实现datetime与时间段之间的运算
datetime类型可以和timedelta类型进行加减运算,用于时间的推算
In [137]: now = datetime.datetime.now()
In [138]: now
Out[138]: datetime.datetime(2018, 3, 30, 16, 12, 3, 808323)
In [139]: now+t1
Out[139]: datetime.datetime(2018, 3, 31, 16, 12, 3, 808323)
两个datetime类型进行减法运算可以得到时间段类型timedelta
In [140]: new_time = datetime.datetime.now()
In [141]: new_time - now
Out[141]: datetime.timedelta(0, 127, 710571)
date格式也可以和timedelta运算,因为date也是一个具体的格式
In [156]: today = datetime.date.today()
In [157]: today
Out[157]: datetime.date(2018, 3, 30)
In [158]: today+t2
Out[158]: datetime.date(2018, 4, 6)
date 类型
date类型的方法与datetime类型类似
In [170]: today = datetime.date.today()
In [171]: today
Out[171]: datetime.date(2018, 3, 30)
In [172]: one_daty = datetime.date(2018,3,4)
In [173]: one_daty
Out[173]: datetime.date(2018, 3, 4)
In [174]: str(today)
Out[174]: '2018-03-30'//转化为时间字符串,然后可以转化为datetime类型
time 类型
time 类型表示一天中的当地时间,与任何特定的日子没有关系
In [176]: datetime.time(5,44,23)
Out[176]: datetime.time(5, 44, 23)
In [177]: str(datetime.time(5,44,23))
Out[177]: '05:44:23'