在Python中,与时间相关的库有好些,可以帮助我们快速的处理与时间相关的需求和问题。
这里想和大家分享一下如何将时间字符串转换为datetime以方便使用和处理。
其实相关的文章可以找到很多,不过感觉很多介绍的是类似于“2014-02-13 20:53:21”这样的时间,这借助于datetime标准库中的strptime方法即可快速转换。不过如果是遇到ISO 8601中有一种日期和时间的组合表示法所表示的时间,如:
2014-02-13 17:33:41.817981+08:00
这里面还包含着时区,处理起来貌似要麻烦一点。
其实我们无非是需要构造时间的每个部分,因此可以找一些方法将以上时间字符串分解开来,然后再用datetime中的方法来构造时间即可。以下是django中的一个实现方法,学习一下还是很不错:
import datetime import re import pytz datetime_re = re.compile( r'(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})' r'[T ](?P<hour>\d{1,2}):(?P<minute>\d{1,2})' r'(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?' r'(?P<tzinfo>Z|[+-]\d{2}:?\d{2})?$' ) def parse_datetime(value): match = datetime_re.match(value) if match: kw = match.groupdict() if kw['microsecond']: kw['microsecond'] = kw['microsecond'].ljust(6, '0') tzinfo = kw.pop('tzinfo') if tzinfo == 'Z': tzinfo = pytz.utc elif tzinfo is not None: offset = 60 * int(tzinfo[1:3]) + int(tzinfo[-2:]) if tzinfo[0] == '-': offset = -offset tzinfo = FixedOffset(offset) kw = dict((k, int(v)) for k, v in six.iteritems(kw) if v is not None) kw['tzinfo'] = tzinfo return datetime.datetime(**kw)
这里使用正则匹配获取到时间的各个部分,然后构造tzinfo,其中的FixedOffset代码如下:
from datetime import timedelta, tzinfo class FixedOffset(tzinfo): "Fixed offset in minutes east from UTC." def __init__(self, offset): if isinstance(offset, timedelta): self.__offset = offset offset = self.__offset.seconds // 60 else: self.__offset = timedelta(minutes=offset) sign = '-' if offset < 0 else '+' self.__name = "%s%02d%02d" % (sign, abs(offset) / 60., abs(offset) % 60) def __repr__(self): return self.__name def __getinitargs__(self): return self.__offset, def utcoffset(self, dt): return self.__offset def tzname(self, dt): return self.__name def dst(self, dt): return timedelta(0)
这样就可以很顺利的得到datetime对象了。
另外,一个很好的第三方包也为我们想到了这一点,那就是python-dateutil,它里面提供的方法也只需要我们将字符串传入即可得到想要的结果,使用示例如下:
>>> import dateutil.parse >>> t = dateutil.parser.parse('2014-02-13 17:33:41.817981+08:00') >>> t datetime.datetime(2014, 2, 13, 17, 33, 41, 817981, tzinfo=tzoffset(None, 28800))
最后再分享一下时区转换:
>>> from dateutil import tz >>> utc = tz.tzutc() >>> t.astimezone(utc) datetime.datetime(2014, 2, 13, 9, 33, 41, 817981, tzinfo=tzutc()) >>> to_zone = tz.gettz('America/Chicago') >>> t.astimezone(to_zone) datetime.datetime(2014, 2, 13, 3, 33, 41, 817981, tzinfo=tzfile('America/Chicago'))