在测试自动化特别是API测试当中,经常遇见这样的case,一个API的返回值是另外一个API的入参,虽然入参和返回值都是一个时间,但入参是datetime类型的变量,返回值是个str类型的变量。 那么如何处理这些时间变量呢?如果这些时间变量跟时区, 夏令时结合在一起时候,如何处理呢?
在我的测试过程中,我遇见这样一个问题
1.一个页面的Book API需要传入一个课的开始时间,这个时间格式要求是string,例如”2017-08-22 08:49:38”
2.Book成功后的返回值包含了一个字典,其中包含时间,也是string格式,但是这个值带时区属性,例如 “starttime_est”:”2017-08-22 08:49:38”.
3.另外一个显示已定课的booked API,也包含一个string格式的时间,但是不带时区信息,默认是local time, 格式如下:”2017-08-22 20:49:38”
那么我现在定了一节eastern的开始时间是”2017-08-22 08:49:38”的课,我页面上看到的是”2017-08-22 20:49:38”, 我如何来验证这节课就是我定的课呢?
Python中对时间的处理,我们一般用datetime模块,datetime对于string和datetime的转换,我们一般用strptime, strftime来实现。
|
|
其中,时间格式定义如下:
|
|
看起来很简单嘛,字符串类型的t2直接用strptime就转换成时间了呀,等等,t1本来是等于t2的,这样转换后t1和t2分别为:
assert t1==t2的结果是False, 为什么呢?因为 t1是aware的时间, t2是naive的时间。 他们的详细区别如下:
There are two kinds of date and time objects: “naive” and “aware”.
An aware object has sufficient knowledge of applicable algorithmic and political time adjustments, such as time zone and daylight saving time information, to locate itself relative to other aware objects. An aware object is used to represent a specific moment in time that is not open to interpretation
A naive object does not contain enough information to unambiguously locate itself relative to other date/time objects. Whether a naive object represents Coordinated Universal Time (UTC), local time, or time in some other timezone is purely up to the program, just like it’s up to the program whether a particular number represents metres, miles, or mass. Naive objects are easy to understand and to work with, at the cost of ignoring some aspects of reality.
很不幸运的是,datetime模块模式生成的是naive类型的datetime对象,例如now(), utcnow()。要想生成aware类型的,可以使用now()接受一个tzinfo对象来生成,但是标准库并不提供任何已实现的tzinfo类。 那么自己实现一个了:
|
|
回到本题中来,我eastern time的时间就解决了
看似没毛病对不对?那是我们没考虑daylight saving啊! 今天Eastern time跟UTC时间相差是-4,到夏令时结束时候,那么就是-5,再有,我国不实行夏令时,
有些国家只有某些地区用夏令时,有些不用。这样我传入的参数-5,-4,都是Eastern time,那我怎么知道这个offset是多少呢?再写个函数判断这些?要累死吧,说不定还写不出来。
这时候就需要巨人的肩膀了, pytz这个第3方库保证了时间的精准性和解决了daylight saving时间切换的问题, 来看看它怎么用。
1.安装:
|
|
2.设定时区:
|
|
3.使用
|
|
大家发现问题了没有。默认的正八区,跟UTC的差距不是+8:00,而是+8:06, 这个是构造时区时没有使用naive的时间。pytz构造本地时间只支持两种方式,且都只能localize naive datetime:
pytz建议我们处理时间一律用UTC的方式, 只有你需要看输出的结果时,才把它转为本地时间。
4.要注意的问题:
如果你需要处理夏令时和时区的转换,pytz推荐我们使用normalize()这个方法, 举例来说,东部时间2017-03-12 日凌晨2点是夏令时起效时间。
到此,我们就掌握了对datetime的如下操作:
1.string 和datetime的转换 –strftime, strptime
2.时区的转换。 –timezone(tz), tz.localize(dt)
3.夏令时的转换。 – tz.normalize(dt)
最后再来看看我们的问题如何解决:
文章的最后,放出我自己封装的一个datetime处理类,以后处理datetime,直接使用即可。