Python日期时间处理总结

使用Python已经一年有余,但是作为一只Java攻城狮,还是会对Python的日期时间处理感觉困惑。
故整理此文,非但总结一下日期时间处理以加深记忆,也为自己的坏记性留下退路。

Python标准库

在Python标准库中,有个datetime模块归类于数据类型,也有一个time模块归类于通用的操作系统服务。

time

time模块提供了各种各样的时间相关方法,它与datetime包和calendar比较类似,但仍有功能性的区别。

据Python官方文档介绍,此包并非完全跨平台的,它的绝大多数函数都依赖于各个操作系统的底层c库,甚至函数名都一样。

time模块中的所有时间,都是相对于epoch的秒值,就类似于java中的long时间戳。

此包有一些术语需要解释一下:

  • epoch: 表示时间的起始原点,在Unix平台上,这个时间原点就是1970-01-01 00:00:00:000。
  • UTC:协调世界时,又成为世界标准时间。比如中国大陆是东8区,时间就可以写为UTC+8
  • DST:夏日节约时间

time()获取当前时间戳

time()会返回浮点数格式的时间戳,整数部分为秒值,小数部分为6位毫秒值。这一点和Java有挺大的区别。

python版获取时间戳:

1
2
3
>>> import time
>>> time.time()
1422763753.864036

作为对比,Java版获取时间戳:

1
2
System.currentTimeMillis();
System.nanoTime();

time()底层借助于unix的gettimeofday()函数。

clock()获取CPU时间

这个函数应该在性能统计时候有用,它比time()应该更有用。

sleep()进行线程睡眠

sleep()函数接受一个秒值进行睡眠,底层调用unix的select()函数实现。

可以传入一个小数,来让睡眠时间小于1秒。

获取非时间戳的struct时间

调用gmtime()可以获取世界标准时间,调用localtime()可以获取本地的标准时间,比如在大陆就是UTC+8时间。

1
2
3
4
>>> time.gmtime()
time.struct_time(tm_year=2015, tm_mon=2, tm_mday=1, tm_hour=4, tm_min=20, tm_sec=58, tm_wday=6, tm_yday=32, tm_isdst=0)
>>> time.localtime()
time.struct_time(tm_year=2015, tm_mon=2, tm_mday=1, tm_hour=12, tm_min=21, tm_sec=7, tm_wday=6, tm_yday=32, tm_isdst=0)

根据struct时间获取时间戳

mktime()函数可以将struct时间转换为毫秒值。

1
2
3
4
>>> time.mktime(time.localtime())
1422765047.0
>>> time.mktime(time.gmtime())
1422736369.0

获取字符串格式的时间

ctime()函数等同于asctime()函数,都是将传入的秒值转换为时间字符串,
但是这两个函数并没有格式化时间字符串的方式。

1
2
3
4
5
6
>>> time.ctime()
'Sun Feb 1 14:29:32 2015'
>>> time.asctime()
'Sun Feb 1 14:29:35 2015'
>>> time.ctime(140000000)
'Sun Jun 9 16:53:20 1974'

strftime()函数可以将struct时间根据传入的模板格式化时间字符串,具体模板的可选参数参见后文。

1
2
3
4
>>> time.strftime('%Y-%m-%d', time.gmtime())
'2015-02-01'
>>> time.strftime('%Y-%m-%d')
'2015-02-01'

将时间字符串解析为时间

strptime()函数可以将字符串解析为时间struct,该函数接受1-2个参数,
解析模板为可选参数,默认的解析模板为%a %b %d %H:%M:%S %Y

如果解析失败则会抛出ValueError。

1
2
3
4
>>> time.strptime('Sun Feb  1 14:29:32 2015')
time.struct_time(tm_year=2015, tm_mon=2, tm_mday=1, tm_hour=14, tm_min=29, tm_sec=32, tm_wday=6, tm_yday=32, tm_isdst=-1)
>>> time.strptime('2015-02-05', '%Y-%m-%d')
time.struct_time(tm_year=2015, tm_mon=2, tm_mday=5, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=36, tm_isdst=-1)

struct_time结构

这个结构体里面的变量值都是整数。

  • tm_year:年份,如2015
  • tm_mon:月份,1-12
  • tm_mday:日期,1-31
  • tm_hour:小时,0-23
  • tm_min:分钟,0-59
  • tm_sec:秒钟,0-59
  • tm_wday:周几,0-6,0表示周一
  • tm_yday:每年的第几天,1-366
  • tm_isdst:0/1/-1

datetime

相较于time模块,datetime内容就太多了,扼要整理吧。

datetime模块中包含多个类,包括date、time、datetime、timedelta、tzinfo。

也包括格式化日期strftime()函数与解析字符串strptime()函数。

date-日期

date类包含三个属性yearmonthday

可以直接通过date(year=2015, month=1, day=12)获取日期对象。

date对象提供timetuple()函数,获取time_struct实例。

其他也提供诸如replace、weekday、isoweekday、isocalendar、isoformat、ctime、strftime函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> date_instance = date(year=2015, month=1, day=15)
>>> date_instance.replace(year=2014)
datetime.date(2014, 1, 15)
>>> date_instance.timetuple()
time.struct_time(tm_year=2015, tm_mon=1, tm_mday=15, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=15, tm_isdst=-1)
>>> date_instance.weekday()
3
>>> date_instance.isoweekday()
4
>>> date_instance.isocalendar()
(2015, 3, 4)
>>> date_instance.isoformat()
'2015-01-15'
>>> date_instance.ctime()
'Thu Jan 15 00:00:00 2015'
>>> date_instance.strftime()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Required argument 'format' (pos 1) not found
>>> date_instance.strftime('%Y-%m-%d %H:%M:%S')
'2015-01-15 00:00:00'

time-时间

time类包含五个属性hourminutesecondmicrosecondtzinfo

可以直接通过time(hour=12, minute=50, second=30, microsecond=300)构造time实例。

time整体上与date一样,只是内部的属性变了而已。它也包含replace、isoformat、strftime函数,以及其他几个无关紧要的函数。

datetime类

datetime等于是date类与time类的合集,包含它们的全部属性。

可以直接通过datetime.now()获取当前日期时间,也可以通过datetime.fromtimestamp()获取实例。

其他还有许多获取日期时间的函数,如:

  • datetime.today()
  • datetime.utcnow()
  • datetime.utcfromtimestamp(timestamp)
  • datetime.fromordinal(ordinal)
  • datetime.combine(date, time)
  • datetime.strptime(date_string, format)

datetime也提供date()函数返回一个date实例,以及一个time()函数返回一个time实例。

与date、time类似,datetime也有replace函数,用于替换实例中的属性。

由于datetime差不多就是date、time的合集,因此date、time有的函数,也都在datetime中粗现了,用法也基本雷同。

timedelta-时间差

timedelta是非常好用的时间计算工具,有了此类就可以在day、second、microsecond三个维度上进行时间运算。

获取明天datetime实例dt.now() + timedelta(1)

1
2
3
4
5
6
>>> from datetime import timedelta
>>> from datetime import datetime as dt
>>> tomorrow = dt.now() + timedelta(1)
>>> tomorrow
datetime.datetime(2015, 2, 2, 16, 20, 2, 895641)
>>>

获取两个时间之间的的时间差:

1
2
3
4
5
6
7
8
9
10
11
>>> tomorrow
datetime.datetime(2015, 2, 2, 16, 20, 2, 895641)
>>> today
datetime.datetime(2015, 2, 1, 16, 21, 39, 313151)
>>> (today-tomorrow).days
-1
>>> (today-tomorrow).seconds
96
>>> (today-tomorrow).microseconds
417510
>>>

比较两个时间大小:

1
2
3
4
5
6
>>> tomorrow
datetime.datetime(2015, 2, 2, 16, 20, 2, 895641)
>>> today
datetime.datetime(2015, 2, 1, 16, 21, 39, 313151)
>>> today > tomorrow
False

格式化与解析

datetime提供的strftime与strptime与time模块类似,无需再写。

calendar

暂不理会。

Python日期格式化模板

Python的日期格式化模板变量如下:

  • %a:周缩写,如Sun表示周日
  • %A:周全拼,如Sunday表示周日
  • %b:月缩写,如Feb表示2月
  • %B:月全拼,如February表示2月
  • %c:本地化的日期时间格式,如“Sun Feb 1 14:47:04 2015”
  • %d:每个月中的几号,01-31
  • %H:24小时中的几点,00-23
  • %I:12小时中的几点,01-12
  • %j:每年中的第几天,001-366
  • %m:每年的第几个月,01-12
  • %M:每个小时中的第几分钟,00-59
  • %p:本地化的上午或下午字符串,AM/PM
  • %s:每个分钟中的第几秒钟,00-59
  • %U:每年的第几周,周日为每周的起点,00-53
  • %w:每周的第几天,周日为起点,0-6
  • %W:每年的第几周,周一为每周的起点,00-53
  • %x:本地化的日期格式,如“02/01/15”
  • %X:本地化的时间格式,如“14:54:48”
  • %y:本世纪的第几年,如2015年为15
  • %Y:公元第几年,如2015
  • %Z:TimeZone名称,如CST
  • %%:无意义,输出一个%