由于从事智能运维 AIOps 相关的算法研究,因此日常接触的最多就是时间序列相关的数据。在不同场景下时间字符串表示的格式可能都不相同,因此本文记录下所了解的字符串解析方法。

time 模块

一般情况下都是将时间字符串转为时间戳或者反之转换,time 模块即可解决问题;

1
2
3
4
5
import time
# 时间戳转为日期
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(t))
# 日期转为时间戳
time.mktime(time.strptime(d, "%Y-%m-%dT%H:%M:%S.%fZ"))

⚠️ 注意:上面时间转换方法操作简单,可以满足大部分需求;但是存在两种问题:

  • 时区问题,例如 UTC 格式;【如果是时间戳就没什么区别?】
  • 字符串格式问题,例如不同的日期字符串格式;

datetime 模块

datetime 模块比 time 模块功能更加丰富;

详细的接口说明参考:https://docs.python.org/zh-cn/3.8/library/datetime.html

例如将 UTC 时间转为本地时间格式:

1
2
3
4
5
6
7
from datetime import datetime, timedelta

utc = "2021-03-08T08:28:47.776Z"
UTC_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"
utc_time = datetime.strptime(utc, UTC_FORMAT)
local_time = utc_time + timedelta(hours=8)
print(local_time.strftime("%Y-%m-%d %H:%M:%S.%f")) # 2021-03-08 16:28:47.776000

时间戳转为时间字符串:

1
2
ts = 1615289959 # datetime.now().timestamp()
datetime.fromtimestamp(1615289959).strftime("%Y-%m-%d %H:%M:%S.%f") # '2021-03-09 19:39:19.000000'

dateutil 模块

dateutil 模块具有扩展时区和解析支持的第三方库,时间解析功能非常强大几乎包含任何形式的时间字符串格式;

详细接口参考文档:https://dateutil.readthedocs.io/en/stable/

参考案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> from dateutil.relativedelta import *
>>> from dateutil.easter import *
>>> from dateutil.rrule import *
>>> from dateutil.parser import *
>>> from datetime import *
>>> now = parse("Sat Oct 11 17:13:46 UTC 2003")
>>> today = now.date()
>>> year = rrule(YEARLY,dtstart=now,bymonth=8,bymonthday=13,byweekday=FR)[0].year
>>> rdelta = relativedelta(easter(year), today)
>>> print("Today is: %s" % today)
Today is: 2003-10-11
>>> print("Year with next Aug 13th on a Friday is: %s" % year)
Year with next Aug 13th on a Friday is: 2004
>>> print("How far is the Easter of that year: %s" % rdelta)
How far is the Easter of that year: relativedelta(months=+6)
>>> print("And the Easter of that year is: %s" % (today+rdelta))
And the Easter of that year is: 2004-04-11

Pytz 模块可以与之共同使用来指定时区;Pytz 参考:https://pypi.org/project/pytz/

参考案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> from datetime import datetime, timedelta
>>> from pytz import timezone
>>> import pytz
>>> utc = pytz.utc
>>> utc.zone
'UTC'
>>> eastern = timezone('US/Eastern')
>>> eastern.zone
'US/Eastern'
>>> amsterdam = timezone('Europe/Amsterdam')
>>> fmt = '%Y-%m-%d %H:%M:%S %Z%z'

>>> loc_dt = eastern.localize(datetime(2002, 10, 27, 6, 0, 0))
>>> print(loc_dt.strftime(fmt))
2002-10-27 06:00:00 EST-0500

>>> ams_dt = loc_dt.astimezone(amsterdam)
>>> ams_dt.strftime(fmt)
'2002-10-27 12:00:00 CET+0100'

其它技巧

macOS :

1
2
3
4
// 将时间戳转为日期
$ date -r 1615289959
// 将日期转为时间戳
$ date -j -f "%Y-%m-%d %H:%M:%S" "2021-03-09 07:10:00" "+%s"

附录

python 中时间日期格式化符号:

  • %y 两位数的年份表示(00-99)
  • %Y 四位数的年份表示(000-9999)
  • %m 月份(01-12)
  • %d 月内中的一天(0-31)
  • %H 24 小时制小时数(0-23)
  • %I 12 小时制小时数(01-12)
  • %M 分钟数(00-59)
  • %S 秒(00-59)
  • %a 本地简化星期名称
  • %A 本地完整星期名称
  • %b 本地简化的月份名称
  • %B 本地完整的月份名称
  • %c 本地相应的日期表示和时间表示
  • %j 年内的一天(001-366)
  • %p 本地 A.M. 或 P.M. 的等价符
  • %U 一年中的星期数(00-53)星期天为星期的开始
  • %w 星期(0-6),星期天为 0,星期一为 1,以此类推。
  • %W 一年中的星期数(00-53)星期一为星期的开始
  • %x 本地相应的日期表示
  • %X 本地相应的时间表示
  • %Z 当前时区的名称
  • %% %号本身