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(awk
、perl
等)可能会加快速度,但如果您需要将结果存储在 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
我有两个日期,格式如下: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(awk
、perl
等)可能会加快速度,但如果您需要将结果存储在 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