这是先前的问题关于bash
我编写的一个脚本,它可以帮助我更准确地跟踪我的恶习。我现在正在尝试修改该脚本以显示所有非零单位:
It's been 2 weeks, 1 day and 5 hours since you last bought a deck.
为此,以下是我迄今为止编写的脚本的相关部分:
last_bought=$(cat "$lb_file") # file contains time in epoch seconds
...
now=$(date -u +%s)
elapsed="$((now-last_bought))"
W=$((elapsed/60/60/24/7))
D=$((elapsed/60/60/24))
H=$((elapsed/60/60%24))
if [[ $W -le 0 && $D -le 0 && $H -gt 0 ]]; then string="$H hours"
elif [[ $W -le 0 && $D -gt 0 && $H -gt 0 ]]; then string="$D days and $H hours"
elif [[ $W -gt 0 && $D -gt 0 && $H -le 0 ]]; then string="$W weeks and $D days"
elif [[ $W -gt 0 && $D -le 0 && $H -gt 0 ]]; then string="$W weeks and $H hours"
elif [[ $W -gt 0 && $D -gt 0 && $H -gt 0 ]]; then string="$W weeks, $D days and $H hours"
fi
这对于小时和天数来说非常有效(运行脚本时,小时值为-b 50
shows 2 days and 2 hours
)。但是,当脚本中输入的小时值至少为一周时,两个都$W
和变量$D
已填充。这意味着对于 (1 周的小时数) 的值-b 168
,输出将为:
It's been 1 weeks and 7 days since you last bought a deck.
我该如何解决这个问题,最好同时实现单数时间段,如下所示:
It's been 1 week and 1 hour since you last bought a deck.
我也意识到我可能以一种非常粗略的方式检查我的逻辑,所以如果有更聪明/更常见的方法,我将不胜感激,并且
答案1
now=$(date +%s)
last_bought=$(date -d '-1 week -3 days -6 hours -34 minutes' +%s)
elapsed=$(( (now - last_bought) / 3600)) # truncate to hours
((hrs = elapsed % 24, elapsed /= 24))
((days = elapsed % 7))
((weeks = elapsed / 7))
echo "$weeks weeks, $days days, $hrs hours"
1 weeks, 3 days, 6 hours
答案2
乍一看,我认为问题在于您正在使用整个经过的时间来评估 W、D、H。
每次评估后,您都应该减少elapsed
该金额。
日期和小时似乎可以正常工作而无需减少的情况最有可能是因为 H 是使用模 24 进行评估的。
还要记住,由于闰年、闰月、夏令时、日历翻转等,日期操作更加复杂。
从片段和明显的用途来看,数学可能已经足够好了。
答案3
之后很多反复试验并查找文档对于bash
非常令人困惑的变量运算符(=/
,=*
等等),我设法调整了Glenn的答案,使其对我有用:
now=$(date +%s)
last_bought=$(date -u +%s)
elapsed=$(((now-last_bought) / 3600))
H=$((elapsed % 24))
D=$(( ( elapsed /= 24 ) % 7))
W=$((elapsed / 7))
echo "$H weeks, $D days, $H hours"
我仍然不完全确定我是否理解变量运算符的工作原理,但无论如何,代码现在似乎按我想要的方式工作。