前几天搞了下时间各种格式之间的转换,记录一下。
Python表示时间主要有两个库,分别是time和datetime。time模块更接近于操作系统,所以其属性也是和Unix timestamp相关比较多。比如其能表示的年份为1970-2038。因为时间戳含义就是从1970-1-1到现在的秒数,用int类型表示,int类型为32bit,表示范围是[-2^31+1 ~2^31-1],即[-2147483648, 2147483648],换成成年大概68年,所以最大有效期为1970+68=2038。
如果想用更大的年份,最好用datetime。其最大年份可以用datetime.MAXYEAR查看,为9999。
time模块介绍
1. struct_time类。此类就是一个完整时间的元组,共有9个元素。如果调用time模块的其他函数,如gmtime(),localtime()和strptime(),那么返回的就是一个struct_time对象,9个元素分别为:
属性 | 值 |
---|---|
tm_year(年) | 如2019 |
tm_mon(月) | 如11 |
tm_mday(日) | 如31,每个月的日有区别 |
tm_hour(小时) | 0-23 |
tm_min(分) | 0-59 |
tm_sec(秒) | 0-59 |
tm_wday(周几) | 0-6(0为周日) |
tm_yday(一年中的第几天) | 1-365 |
tm_isdst(是否夏令时) | 默认为-1 |
2. time.time() 获取当前时间的时间戳
3. time.localtime() 将时间戳转化为struct_time格式,时区为当前时区
4. time.gmtime() 将时间戳转化为UTC时间的struct_time
5. time.mktime() 将struck_time转化为时间戳
6. time.sleep() 睡眠时间,单位是秒
7.time.asctime() 将struct_time表示为这种形式"Fri Nov 08 14:47:02 2019"。默认以time.localtime()为参数
8. print time.ctime() 将时间戳表示为这种形式"Fri Nov 08 14:47:02 2019"。默认以time.time()为参数
9. time.strftime(format[,t]) 将时间元组struct_time转化为format格式的字符串, 如果t没有指定,那么默认以time.localtime()为时间。时间格式为:
时间格式 | 含义 |
---|---|
%a | 本地(locale)简化星期名称 |
%A | 本地完整星期名称 |
%b | 本地简化月份名称 |
%B | 本地完整月份名称 |
%c | 本地相应的日期和时间表示 |
%d | 一个月中的第几天(01 - 31) |
%H | 一天中的第几个小时(24小时制,00 - 23) |
%I | 第几个小时(12小时制,01 - 12) |
%j | 一年中的第几天(001 - 366) |
%m | 月份(01 - 12) |
%M | 分钟数(00 - 59) |
%p | 本地am或者pm的相应符 |
%S | 秒(01 - 61) |
%U | 一年中的星期数。(00 - 53星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第0周。 |
%w | 一个星期中的第几天(0 - 6,0是星期天) |
%W | 和%U基本相同,不同的是%W以星期一为一个星期的开始。 |
%x | 本地相应日期 |
%X | 本地相应时间 |
%y | 去掉世纪的年份(00 - 99) |
%Y | 完整的年份 |
%Z | 时区的名字(如果不存在为空字符) |
%% | ‘%’字符 |
如:time.strptime('%Y-%m-%d %H:%M:%S', time.localtime())
注:
“%p”只有与“%I”配合使用才有效果。
当使用strptime()函数时,只有当在这年中的周数和天数被确定的时候%U和%W才会被计算。
10. time.strptime() 于time.strftime()相反,这个函数将字符串时间转化为时间元组struct_time。
如: time.strptime('2019-10-18 16:04:36', '%Y-%m-%d %H:%M:%S')
三者关系如图:
datetime模块介绍
datetime功能相比time更加丰富,模块下又包含了几个类:
类名 | 功能说明 |
---|---|
date | 日期对象 |
time | 时间对象 |
datetime | 日期时间对象 |
datetime_CAPI | 日期时间对象C语言接口 |
timedelta | 时间间隔,即两个时间点之间的长度 |
tzinfo | 时区信息对象 |
1. date类
date类基本元素由年月日组成。可以通过datetime.date.max和datetime.date.min查看其表示的范围
1) 构造函数datetime。可以这样搞
d = datetime.date(2019,8,7)
print d
打印2019-08-07,注意的是这个2019-08-07并不是字符串,而是datetime类的对象
2) datetime.date.today() 返回当前日期,如:
datetime.date.today()
Out[217]: datetime.date(2019, 11, 8)
3)datetime.date.fromtimestamp() 根据给定的时间戳,返回一个date对象, 如:
datetime.date.fromtimestamp(1569895835)
Out[218]: datetime.date(2019, 10, 1)
4) datetime.date.weekday() 参数是一个datetime对象,返回今天是一周的第几天,从周一(0)开始算
t = datetime.date.today() //今天是周五
datetime.date.weekday(t)
Out[221]: 4
5) datetime.date.isoweekday() 以date对象为参数,返回今天是周几,周一返回1,周二返回2...
t = datetime.date.today() //今天是周五
datetime.date.isoweekday(t)
Out[223]: 5
6) datetime.date.isocalendar() 以date对象为参数,返回一个元组,包括年,今天是本年第几周,今天是星期几
t = datetime.date.today() //今天是2019.11.8
datetime.date.isocalendar(t)
Out[224]: (2019, 45, 5)
7) datetime.date.strftime(format) 参数为格式化的字符串,比如'%Y-%m-%d %H:%M:%S',返回值是一个字符串
d = datetime.date(2019,8,7)
format = '%Y-%m-%d %H:%M:%S'
print d.strftime(format)
8)datetime.date.replace() 参数为要替换的新值,返回替换后的datetime对象
d = datetime.date(2019,8,7)
format = '%Y-%m-%d %H:%M:%S'
d1 = d.replace(2018)
print d1.strftime(format) //2018-08-07 00:00:00
d1 = d.replace(month=5)
print d1.strftime(format) //2019-05-07 00:00:00
9) datetime.date.year month day 输出当前datatime对象的年月日
d = datetime.date(2019,8,7)
print d.year, d.month, d.day //2019 8 7
也可以通过getattribute方法来获取属性值:
d = datetime.date(2019,1,1)
print d.__getattribute__('year'), d.__getattribute__('month'), d.__getattribute__('day')
10) datetime.date.isoformat() 返回yyyy-mm-dd格式的字符串
print datetime.date(2019,8,7).isoformat() //2019-08-07
11) datetime.date.timetuple() 返回time模块的struct_time格式元组
d = datetime.date(2019,8,7)
print d.timetuple() // time.struct_time(tm_year=2019, tm_mon=8, tm_mday=7, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=219, tm_isdst=-1)
12) datetime.date.toordinal() 返回公元元历(1年1月1日)开始到现在的天数。
d = datetime.date(2019,1,1)
print d.toordinal() //737060。不知道它怎么算的,如果1年1月1日是1,那么2019.1.1和这个日期相差了2018 * 365 天,结果应该是736570而不是737060,理解有问题
13) datetime.date.fromordinal() toordinal的相反操作,传入一个天数,返回日期
d = datetime.date(2019,1,1)
a = d.toordinal()
print datetime.date.fromordinal(a)
14)日期的比较,例子如下:
d1 = datetime.date(2019,1,1)
d2 = datetime.date(2019,1,2)
d3 = datetime.date(2019,1,1)
print d1.__ge__(d3) //True
print d1.__gt__(d2) //False
print d1.__eq__(d2) //False
print d1.__eq__(d3) //True
print d1.__le__(d2) //True
print d2.__lt__(d3) //False
15) 能表示的最大和最小值min(),max()
print datetime.date.min //0001-01-01
print datetime.date.max //9999-12-31
16) 能表示的最小单位datetime.date.resolution
print datetime.date.resolution //1 day, 0:00:00
2. time类
datetime.date类最小单位为天,datetime.time类为毫秒
time类由小时,分钟,秒,微妙和tzinfo组成。类似的,其构造函数为:
time([hour[, minute[, second[, microsecond[, tzinfo]]]]])
1) datetime.time(15,23,45,368) 返回值为time类的对象
datetime.time(hour=15,minute=23,second=45,microsecond=36800) //结果为15:23:45.036800
2) 获取time对象的属性值
d = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
print d.hour,d.minute,d.second,d.microsecond,d.tzname() //输出结果为15 23 45 36800 None
与datetime.date类似,也可以通过getattribute方法获取, 如:
d = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
print d.__getattribute__('hour'), d.__getattribute__('minute'), d.__getattribute__('second'), d.__getattribute__('microsecond')
3) 按照格式转为为字符串对象datetime.time.strftime('%H:%M:%S')
d = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
print d.strftime('%H:%M:%S')
4)查看时区信息d.tzname()
d.tzname()
5) 替换某个时间datetime.time.replace(),与date类似
d = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
print d.strftime('%H:%M:%S')
d1 = d.replace(hour=19)
print d1 //19:23:45.036800
d1 = d.replace(minute=35)
print d1 //15:35:45.036800
d1 = d.replace(second=36)
print d1 //15:23:36.036800
d1 = d.replace(microsecond=66000)
print d1 //15:23:45.066000
6) datetime.date.isoformat() 返回'%H:%M:%S'格式的字符串
d = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
print d.isoformat() //15:23:45.036800
7) 最大最小值min, max
print datetime.time.min //00:00:00
print datetime.time.max //23:59:59.999999
8) 能表示的最小单位datetime.time.resolution
print datetime.time.resolution //0:00:00.000001
3. datetime类
datetime.datetime类是date类和time类的合体,函数的类型和含义都很类似,只是相较于date或者time进行了扩充。比如说datetime类的构造函数:
datetime(self, year, month, day, hour=None, minute=None, second=None, microsecond=None, tzinfo=None)
1) datetime.resolution 能表示的最小时间单位
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.resolution //0:00:00.000001
2) datetime.date() 获取表示日期的部分
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.date() //2019-11-11
3) datetime.time() 获取表示时间的部分:
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.time()
4)datetime.isoformat() 返回iso格式时间串
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.isoformat() //2019-11-11T16:33:24.666000
5) datetime.utcfromtimestamp(timestamp) 参数为时间戳,返回值为datetime对象
print datetime.utcfromtimestamp(time.time()) //返回utc时间2019-11-12 08:04:54.660000,当前时间为2019-11-12 16:04:54
6)datetime.replace 用法date和time
7)datetime.strftime() 将datetime时间格式化为字符串
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.strftime('%Y-%m-%d %H:%M:%S') //2019-11-11 16:33:24
8) datetime.strptime() 参数为时间字符串,和时间格式,返回datetime对象
print datetime.datetime.strptime('2019-3-26 7:18:16', format) //2019-03-26 07:18:16
9) datetime.timetuple() 将datetime对象转化为time模块的struct_time
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.timetuple() //time.struct_time(tm_year=2019, tm_mon=11, tm_mday=11, tm_hour=16, tm_min=33, tm_sec=24, tm_wday=0, tm_yday=315, tm_isdst=-1)
10) datetime.today() 获取今天的时间,返回值为datetime对象
print datetime.datetime.today() //2019-11-12 11:43:35.904000
11) datetime.weekday(),fromordinal(), toordinal(), isoweekday(), isocalendar() 同date
12) datetime.utcnow() 返回当前标准时区的时间对象
print datetime.datetime.utcnow() //返回值为2019-11-12 03:52:00.943000;当前北京时间为2019-11-12 11:52:00.943000
13)可以通过datetime.year/month/day/hour/minute/second/microsecond 来获取datetime对象的具体某个时间值:
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.month, d.hour, d.second
14) datetime.fromtimestamp() 参数为timestamp, 返回datetime对象
datetime.datetime.fromtimestamp(time.time()) //返回2019-11-12 16:06:16.437000,即当前时间
15)datetime.ctime() 同date类
16)datetime.astimezone() 传入参数是一个timezone,根据时区设置,返回datetime对象。需要注意的是,转化前的datetime是需要有时区信息才可以的。
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8))
print d.astimezone(UTC(7)) //2019-11-11 15:33:24.666000+07:00, 此处UTC是一个自己创建的类,详见tzinfo章节
17)datetime.combine() 将date和time组合成datetime对象
a1 = datetime.date(2019,1,1)
d1 = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
datetime.datetime.combine(a1, d1) //2019-01-01 15:23:45.036800
18) datetime.now() 返回当前时间的datetime对象(带时区)
print datetime.datetime.now() //2019-11-12 17:22:00.501000
19) datetime.tzname(),datetime.utcoffset, datetime.dst() 见tzinfo
20) datetime.utctimetuple() 创建utc时间的time模块的struct_time结构
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8))
print d.utctimetuple()
21) 类似于date模块,datetime模块也可以用__gt__等进行比较
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8))
d1 = datetime.datetime(2019,11,12,16,33,24,666000,tzinfo=UTC(8))
print d1.__gt__(d) //返回True
3. timedelta类
timedelta类用来进行日期时间的运算,最大单位是天,最小单位是微妙。其构造函数为:
datetime.timedelta(days=0, seconds=0, microseconds=0,milliseconds=0, minutes=0, hours=0, weeks=0)
1) timedelta的使用
timedelta中参数的值分为正负,正值为加,负值为减。比如先创建了一个datetime对象d
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8))
如果要计算时间d之后一天,一小时,一分钟,一秒,一毫秒和一微妙后的时间是多少就可以这么做:
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8))
print d + datetime.timedelta(days=-1,hours=1,minutes=1,seconds=1,microseconds=1,milliseconds=1) //2019-11-10 17:34:25.667001+08:00
2) timedelta.days 返回timedelta有多少整天,不包含小时和分钟, 如:
td = datetime.timedelta(days=13,hours=2,minutes=3,seconds=1,microseconds=1,milliseconds=1)
print td.days //返回13
4. tzinfo类
tzinfo类是一个虚拟类,如果要使用的话,需要创建一个子类,并实现相关方法。需要重写的方法有name(),utcoffset(),dst()这三个方法。
class UTC(tzinfo): """UTC""" def __init__(self,offset = 0): self._offset = offset def utcoffset(self, dt): return timedelta(hours=self._offset) def tzname(self, dt): return "UTC+%s" % self._offset def dst(self, dt): return timedelta(hours=self._offset)
创建一个北京时间的datetime
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8)) print d.tzname(), d.utcoffset(), d.dst() #打印结果:UTC+8 8:00:00 8:00:00
需要注意的是,tzinfo是要和datetime一起使用的,如果直接创建一个UTC对象,打印tzname需要同时传入一个datetime对象才可以,看定义就比较明白了。
如果不想自己实现tzinfo,可以用现成的库pytz
pytz中可以直接通过pytz.timezone()获取一个对象,比如要获取上海的,可以是:
pytz.timezone('Asia/Shanghai')
5. 实用举例
1. 获取Linux时间戳
1) 获取当前时间的时间戳
print time.time()
2)获取特定时间的时间戳
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=pytz.UTC) print time.mktime(d.timetuple()) #1573461204.0
或者这样
timeStr = '2019-10-01 10:10:35' //指定一个时间
timearray = time.strptime(timeStr, '%Y-%m-%d %H:%M:%S') //将时间按照格式转化为time.struct_time格式
print timestemp = time.mktime(timearray) //生成时间戳1569895835.0
廖雪峰老师的网站上有一种方法是调用
>>> dt = datetime(2015, 4, 19, 12, 20) # 用指定日期时间创建datetime
>>> dt.timestamp() # 把datetime转换为timestamp
但是这种方法我这边没有不成功,可能是库不对
2. 获取时间字符串
1) 利用time模块获取当前时间字符串
format = '%Y-%m-%d %H:%M:%S' print time.strftime(format)
这种方法利用了strftime默认以time.localtime()为第二个参数,获取当前时间
2) 利用datetime模块获取当前时间字符串
format = '%Y-%m-%d %H:%M:%S' dt = datetime.datetime.now() print dt.strftime(format)
datetime.now()返回的是datetime对象,再利用strftime转化为字符串
3)将timestamp转化为时间字符串
print datetime.datetime.fromtimestamp(timestamp)
也可以利用time模块转化为字符串格式
format = '%Y-%m-%d %H:%M:%S' timestamp = 1573461204 print time.strftime(format, time.localtime(timestamp))
4)时区转化
有一点需要明确,就是timestamp是和时区没有关系的,就是说,无论哪个时区,时间确定了,那么时间戳就是固定的。
首先定义一下epoch time,对于格林威治时间,epoch time就是1970年01月01日00时00分00秒,对于北京时间就是1970年01月01日08时00分00秒
如果现在是北京时间2019-11-29 15:00:00,北京时间属于UTC+8时区,那么此时,UTC+0时区的时间就是2019-11-29 07:00:00。此时北京时间的时间戳为2019-11-29 15:00:00 - 1970-1-1 08:00:00的秒数,UTC+0时间的时间戳为2019-11-29 07:00:00 - 1970-1-1 07:00:00的秒数,二者是相等的
反过来,对于一个给定的timestamp,对于不同的时区,就是不同的时间,因为不同的时间epoch time就是不同的了
a. 可以通过datetime的函数astimezone转化
dt = datetime.datetime.now().replace(tzinfo=pytz.timezone('Asia/Shanghai')) print dt #print 2019-11-29 15:34:49.802000+08:06 print dt.astimezone(pytz.timezone('UTC')) #print 2019-11-29 07:28:49.802000+00:00