Bash中两个日期时间相减无法得到有效结果的求助
在Bash中计算两个时间字符串的时间差
首先要解决两个核心问题:一是时间格式不统一(TimeA用逗号分隔毫秒部分,TimeB用点),二是Bash无法直接对字符串做时间运算,必须先转换为可计算的时间戳。
步骤1:统一时间格式
先把TimeA里的逗号替换成点,和TimeB的格式对齐:
TimeA_fixed=$(echo "$TimeA" | tr ',' '.')
步骤2:将时间字符串转为Unix时间戳
使用GNU date命令(主流Linux发行版默认支持),把时间字符串转换成带小数的Unix时间戳(单位:秒):
# 转换为保留两位小数的时间戳 timestamp_A=$(date -d "$TimeA_fixed" +%s.%N | cut -c1-10) timestamp_B=$(date -d "$TimeB" +%s.%N | cut -c1-10)
注:
%s输出秒数,%N输出纳秒,cut -c1-10用来截取到小数点后两位,匹配你的时间精度。
步骤3:计算时间差并格式化输出
用bc命令做浮点运算得到秒级差值,再转换为易读的时分秒格式:
# 计算时间差(单位:秒) diff_seconds=$(echo "$timestamp_B - $timestamp_A" | bc) # 转换为时分秒 hours=$(echo "$diff_seconds / 3600" | bc) remaining_seconds=$(echo "$diff_seconds % 3600" | bc) minutes=$(echo "$remaining_seconds / 60" | bc) seconds=$(echo "$remaining_seconds % 60" | bc) # 输出结果 echo "任务运行时长:${hours}小时${minutes}分钟${seconds}秒"
完整整合脚本
把上述步骤嵌入你的原有脚本中,同时增加有效性检查避免"N/A"问题:
# 读取日志输入的最后日期并提取时间 TimeA="$(tac /pipeline.log | grep log.inputs.jdbc -m 1 | grep -Eo '[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}T[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}.[[:digit:]]{2}')" # 读取最后一个时间戳 TimeB="$(curl -s -XGET -k -u username:password URL/index/_search -H "Content-Type: application/json" -d '{"query":{"query_string":{"query":"ACCOUNT*"}}}' | grep -Eo '@timestamp":"[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{2}' | tail -n1 | grep -Eo '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{2}')" # 处理格式不一致问题 TimeA_fixed=$(echo "$TimeA" | tr ',' '.') # 转换为时间戳并检查有效性 if ! timestamp_A=$(date -d "$TimeA_fixed" +%s.%N 2>/dev/null | cut -c1-10); then echo "TimeA格式无效或无法解析" exit 1 fi if ! timestamp_B=$(date -d "$TimeB" +%s.%N 2>/dev/null | cut -c1-10); then echo "TimeB格式无效或无法解析" exit 1 fi # 计算并格式化时间差 diff_seconds=$(echo "$timestamp_B - $timestamp_A" | bc) hours=$(echo "$diff_seconds / 3600" | bc) remaining=$(echo "$diff_seconds % 3600" | bc) minutes=$(echo "$remaining / 60" | bc) seconds=$(echo "$remaining % 60" | bc) echo "任务运行时长:${hours}h ${minutes}m ${seconds}s"
注意事项
- 若使用macOS,默认的
date是BSD版本,需先安装coreutils(brew install coreutils),然后用gdate替代脚本中的date。 - 如需保留毫秒精度,可将
cut -c1-10改为cut -c1-13,输出时带上毫秒部分。
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

