Bash:计算与 "YYYYMMDDHH" 这样的输入的时差(以小时为单位)

Bash: Calculate the time differences in hours from input like "YYYYMMDDHH"

我有两个日期,格式如下:YYYYMMDDHH,我想计算这两个日期之间的差异(以小时为单位)。例如

start_date=1996010100
end_date=1996010122

代表两个日期:1996-01-01 00:00:00 和 1996-01-01 22:00:00。我想用date来计算时差,结果应该是22小时。我试过

START=$(date -d "$start_date" +"%s")
END=$(date -d "$end_date" +"%s")
HOURS=$(bc -l <<< "($END - $START) / 3600")

但是失败了... 那我该怎么做呢?谢谢!

which stands for two dates: 1996-01-01 00:00:00

因此,如果它代表它,请将其转换为该形式。

start_date=1996010100
start_date=$(sed -E 's/(....)(..)(..)(..)/-- :00:00/' <<<"$start_date")
start=$(date -d "$start_date" +"%s")

end同理[=​​12=]

出于性能原因,我们希望限制需要调用的 sub-process 个调用的数量:

  • 使用 bash 子字符串功能将输入转换为可用的 date/time 字符串
  • bash数学代替bc调用

bash 子字符串功能将输入分解为可用的 date/time 格式,例如:

# convert to usable date/time format:

$ start_date=1996010100
$ echo "${start_date:0:4}-${start_date:4:2}-${start_date:6:2} ${start_date:8:2}:00:00"
1996-01-01 00:00:00

# convert to epoch/seconds:

$ start=$(date -d "${start_date:0:4}-${start_date:4:2}-${start_date:6:2} ${start_date:8:2}:00:00" +"%s")
$ echo $start
820476000

应用于${end_date}并使用bash数学:

$ end_date=1996010122
$ end=$(date -d "${end_date:0:4}-${end_date:4:2}-${end_date:6:2} ${end_date:8:2}:00:00" +"%s")
$ echo $end
820555200

$ hours=$(( (end - start) / 3600))
$ echo $hours
22

这给我们留下了 2 sub-process 个调用 ($(date ...))。虽然其他 languages/tools(awkperl 等)可能会加快速度,但如果您需要将结果存储在 bash 变量中,那么您正在寻找至少需要 1 sub-process 次调用(即 hours=$(awk/perl/??? ...))。

如果性能真的很重要(例如,需要执行这 1000 次),请查看使用 fifo、后台 date 进程和 io 重定向的 this SO answer ... 是的,编码更多一点,更复杂一点,但对于大量操作也更快一点。

最简单的方法是使用此命令安装“dateutils”

sudo apt-get install dateutils

运行 这些命令以秒为单位获得差异:

dateutils.ddiff -i '%Y%m%d%H%M%S' 20200817040001 20210817040101

输出:

31536060s

下一步:简单地除以 86400 得到天数或类似的小时数和分钟数:)

busybox date 可以做到这一点

start_date=1996010100
end_date=1996010122

START=$(busybox date -D "%Y%m%d%H" -d "$start_date" +"%s")
END=$(busybox date -D "%Y%m%d%H" -d "$end_date" +"%s")
HOURS=$(bc -l <<< "scale=0;($END - $START) / 3600")
echo $HOURS

如果您可以使用更 fully-featured 的脚本语言,例如 Python,它将提供更愉快和更易于理解的日期解析体验,并且可能默认安装(datetime 也是一个标准的 Python 库)

使用 shell 变量构建

start_date=1996010100
end_date=1996010122
python -c "import datetime ; td = datetime.datetime.strptime('${end_date}', '%Y%m%d%H') - datetime.datetime.strptime('${start_date}', '%Y%m%d%H') ; print(int(td.total_seconds() / 3600))"

构造为从 stdin

中读取日期和格式代码
echo '%Y%m%d%H' 1996010100 1996010122 | python -c "import datetime,sys ; fmt, date_start, date_end = sys.stdin.read().strip().split() ; td = datetime.datetime.strptime(date_end, fmt) - datetime.datetime.strptime(date_start, fmt) ; print(int(td.total_seconds() / 3600))"

应该与 Python 3 和 Python 2.7

一起工作

此处提供格式代码(1989 C 标准)
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes