Back to prev

Time Process With Effective

Jun 10, 2021
Linkang Chan
@Jesse Chan

本篇笔记主要记录有关时间处理的内容,不同的编程语言或者库对时间的处理都不尽相同。有些不常用的语言,在需要处理时间时总是要搜寻一番,故在此记录整理下时间的处理相关内容。

Linux

Linux 上一般使用date命令操作时间,这在脚本中使用比较方便。

1. 时间差

datediff() {
    d1=$(date -d "$1" +%s)
    d2=$(date -d "$2" +%s)
    echo $(( (d1 - d2) / 86400 )) days
}

$ datediff '2021-04-03' '2019-04-03'

2. 时间计算

$ date -d 'now + 3 weeks'
Thu Jul  1 18:29:18 CST 2021
$ date -d 'Aug 4 + 3 weeks'
Wed Aug 25 00:00:00 CST 2021
$ date -d 'Jan 1 1982 + 11 weeks'
Fri Mar 19 00:00:00 EST 1982

[Reference]: Quickly calculate date differences

Wheels

在此记录一些和时间处理相关的工具或者库,兴许在关键时间能够派上用场。

[dateutils]: 处理时间和日期的命令行工具tool
[go-naturaldate]: Go 语言编写的时间日期解析库lib

Python

计算时间差

当我们从一个时间字符串中解析时间并通过这个时间来计算时间差时,需要注意一些细节。比如:

>>> import datetime
>>> import time
>>> def convertToMs(timeStr):
...     second, ms = timeStr.split(',')
...     dt = datetime.datetime.strptime(second, "%Y-%m-%d %H:%M:%S")
...     return time.mktime(dt.timetuple()) + (int(ms)/1000.)
...
>>> a = convertToMs('2022-01-05 12:23:45,78')
>>> a
1641356625.078
>>> b = convertToMs('2022-01-05 12:23:45,128')
>>> b
1641356625.128
>>> print(f'{b-a:^15.03f}')
     0.050
>>>

注意这边的a的毫秒格式,当使用

>>> dt = datetime.datetime.strptime('2022-01-05 12:23:45,78', "%Y-%m-%d %H:%M:%S,%f")
>>> dt
datetime.datetime(2022, 1, 5, 12, 23, 45, 780000)

这边会在将78补全 6 位,变成780000,这个是微秒的格式。这可能与我们期望的结果不符。因为 strptime 采用的是 1989 C standard 的格式去解析的。 所以当我们在使用这类时间字符串时,需要保证毫秒的精度是对齐的。比如:

t1 = '2022-01-05 12:23:45,078'
t2 = '2022-01-05 12:23:45,898'

这样计算出来的时间差才是我们预期的结果。此时我们可以使用如下的方式来计算时间差:

def convertToMs2(timeStr):
    dt = datetime.datetime.strptime(timeStr, "%Y-%m-%d %H:%M:%S,%f")
    epoch = datetime.datetime.fromtimestamp(0)
    return (dt-epoch).total_seconds()

输出时间格式化

>>> from datetime import datetime
>>> datetime.utcnow().isoformat(sep=' ', timespec='milliseconds')
'2022-01-05 02:29:27.526'
>>> datetime.now().isoformat(sep=' ', timespec='milliseconds')
'2022-01-05 10:38:50.783'
>>> datetime.now().isoformat(sep=' ', timespec='microseconds')
'2022-01-05 10:38:55.142289'

这边采用的 iso8601 的形式,毫秒(milliseconds)使用的是 3 位数表示的, 微秒(microseconds)使用的是 6 位数表示的。