在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\d{4})-(?P\d{1,2})-(?P\d{1,2})'
r'[T ](?P\d{1,2}):(?P\d{1,2})'
r'(?::(?P\d{1,2})(?:\.(?P\d{1,6})\d{0,6})?)?'
r'(?PZ|[+-]\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'))