tl;dr
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s)) / (60*60*24) ))
小心!这里的许多 bash 解决方案都因跨越夏令时开始日期(如果适用)的日期范围而被破坏。这是因为 $(( math )) 构造对结果值执行“地板”/截断操作,仅返回整数。让我举例说明:
DST 于今年 3 月 8 日在美国开始,所以让我们使用跨越该日期的日期范围:
start_ts=$(date -d "2015-03-05" '+%s')
end_ts=$(date -d "2015-03-11" '+%s')
让我们看看我们用双括号得到了什么:
echo $(( ( end_ts - start_ts )/(60*60*24) ))
返回“5”。
使用“bc”更准确地执行此操作会给我们带来不同的结果:
echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc
返回 '5.95' - 缺少的 0.05 是 DST 切换丢失的小时数。
那么这应该如何正确完成呢?
我建议改用这个:
printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)
在这里,'printf' 对由 'bc' 计算的更准确的结果进行四舍五入,为我们提供了正确的日期范围 '6'。
编辑:在下面@hank-schultz 的评论中突出显示答案,这是我最近一直在使用的:
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) ))
只要您始终从较晚的日期中减去较早的日期,这也应该是闰秒安全的,因为闰秒只会增加差异 - 截断有效地向下舍入到正确的结果。