Bash:根据输入(如“YYYYMMDDHH”)计算时间差(以小时为单位)

发布于 2025-01-19 21:04:11 字数 406 浏览 0 评论 0原文

我有两个形式的日期:yyyymmddhh,并想计算这两个日期之间的差异(小时)。例如,

start_date=1996010100
end_date=1996010122

该日期为两个日期:1996-01-01 00:00:00和1996-01-01 22:00:00。我想使用日期来计算小时的差异,结果应为22小时。我尝试了

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

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

I have two dates in forms like: YYYYMMDDHH and want to calculate the differences (in hours) between these two dates. For example

start_date=1996010100
end_date=1996010122

which stands for two dates: 1996-01-01 00:00:00 and 1996-01-01 22:00:00. I want to use date to calculate the difference in hours, the result shall be 22 hours. I tried with

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

but it failed...
So how can I do this? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

灰色世界里的红玫瑰 2025-01-26 21:04:11

出于绩效原因,我们要限制需要调用的子过程呼叫的数量:

  • 使用bash子字符串功能将输入转换为可用的日期/时间字符串
  • 使用bash数学替换bc调用

bash substring功能将输入分解为可用的日期/时间格式,例如:

# 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个子过程调用($(date ...))。虽然其他语言/工具(awkperl等)可能会加快速度,如果您需要将结果存储在bash 变量,然后您正在考虑至少需要1个子过程调用(即,hours = $(awk/perl/??? ...))。

如果性能真的很重要(例如,需要执行此1000次的时间),请看一下 So Ansher 使用FIFO,背景date过程和IO重定向...是的,编码更多,更令人费解,但对于大量操作而言也更快。

For performance reasons we want to limit the number of sub-process calls we need to invoke:

  • use bash substring functionality to convert inputs into usable date/time strings
  • use bash math to replace bc call

bash substring functionality to break the inputs into a usable date/time format, eg:

# 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

Applying to ${end_date} and using bash math:

$ 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

This leaves us with 2 sub-process calls ($(date ...)). While other languages/tools (awk, perl, etc) can likely speed this up a bit, if you need to store the result in a bash variable then you're looking at needing at least 1 sub-process call (ie, hours=$(awk/perl/??? ...)).

If performance is really important (eg, needing to perform this 1000's of times) take a look at this SO answer that uses a fifo, background date process and io redirection ... yeah, a bit more coding and a bit more convoluted but also a bit faster for large volumes of operations.

转瞬即逝 2025-01-26 21:04:11

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

busybox date can do the trick

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
雪若未夕 2025-01-26 21:04:11

代表两个日期:1996-01-01 00:00:00

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

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

和结束一样。

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

So convert it to that form if it stands for it.

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

and the same with end.

辞旧 2025-01-26 21:04:11

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

sudo apt-get install dateutils

运行这些命令以获取秒数差异:

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

输出:

31536060s

下一步:只需除以 86400 即可获取天数或类似的小时和分钟:)

the most simple way is to install "dateutils" using this command

sudo apt-get install dateutils

Run these commands to get the difference in seconds:

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

output:

31536060s

next step: Simply divide by 86400 to get the number of days or similarly for hours and minutes :)

稍尽春風 2025-01-26 21:04:11

如果您可以使用像 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

If it's possible for you to use a more fully-featured scripting language like Python, it'll provide a much more pleasant and understandable date parsing experience, and is probably installed by default (datetime is also a standard Python library)

Structured with shell vars

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))"

Structured to read dates and format code from 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))"

Should work with both Python 3 and Python 2.7

format codes available here (1989 C standard)
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文