我正在尝试将这个时间格式翻译21410.912099
成这个12d 1h 14m 17.912 s
我尝试使用这样的脚本,但它不起作用(无法解析点):(
converts() {
t=$1
d=$((t/60/60/24))
h=$((t/60/60%24))
m=$((t/60%60))
s=$((t%60))
if [ $d -gt 0 ]; then
[ $d = 1 ] && printf "%d day " $d || printf "%d days " $d
fi
if [ $h -gt 0 ]; then
[ $h = 1 ] && printf "%d hour " $h || printf "%d hours " $h
fi
if [ $m -gt 0 ]; then
[ $m = 1 ] && printf "%d minute " $m || printf "%d minutes " $m
fi
if [ $d = 0 ] && [ $h = 0 ] && [ $m = 0 ]; then
[ $s = 1 ] && printf "%d second" $s || printf "%d seconds" $s
fi
printf '\n'
}
答案1
使用 as 分隔符将值拆分为数组.
。
使用 Bash 内置功能printf
将秒重新格式化为自纪元以来的间隔。
$ Input=1721410.912099
$ IFS='.' s_ms=( ${Input} )
$ declare -p s_ms
declare -a s_ms=([0]="1721410" [1]="912099")
$ printf -v Out '%(%-dd %-Hh %-Mm %-S)T.%s s' "${s_ms[0]}" "${s_ms[1]:0:3}"
$ declare -p Out
declare -- Out="20d 23h 10m 10.912 s"
编辑:抱歉,这至少在三个方面有问题。我用 测试了它3707.001234
。
(1) 日期有一次性误差,因为基数是1970-01-01。
(2)它在时间上有一个一次性错误,我无法立即看到(我在格林威治标准时间,但时区是明显的嫌疑人)。date -d @0
报道Thu 1 Jan 01:00:00 BST 1970
也。英国夏令时间一月???
(3) 上述间隔2678400
将丢弃整个月份。
棘手的事情,这些日期。我很抱歉。但如何处理几分之一秒是正确的——解析它并对其进行子串化。
来自 Google 的补充:BST 和英国实验
英国夏令时 (BST) 全年有效,从 1968 年 2 月到 1971 年 10 月。
答案2
对于时间的小数部分,可以使用 ${var##prefix}
和${var%%suffix}
扩展来分割该值。它们从 的值中删除最长的匹配前缀和后缀$var
。
因此添加了两行注释:
converts() {
t=$1
case $t in
*.*) tfrac=${t##*.} # fractional seconds
t=${t%%.*} # full seconds
;;
*) tfrac=0 # no decimal point
;;
esac
d=$((t/60/60/24))
h=$((t/60/60%24))
m=$((t/60%60))
s=$((t%60))
if [ $d -gt 0 ]; then
[ $d = 1 ] && printf "%d day " $d || printf "%d days " $d
fi
if [ $h -gt 0 ]; then
[ $h = 1 ] && printf "%d hour " $h || printf "%d hours " $h
fi
if [ $m -gt 0 ]; then
[ $m = 1 ] && printf "%d minute " $m || printf "%d minutes " $m
fi
if [ $d = 0 ] && [ $h = 0 ] && [ $m = 0 ]; then
[ $s = 1 ] && printf "%d second" $s || printf "%d seconds" $s
fi
printf '\n'
}
我们得到例如
$ converts $(( 1*86400 + 23*3600 + 45*60 + 6))
1 day 23 hours 45 minutes
在尝试删除部分输入之前,我们需要检查输入是否有小数点,因为如果没有点,则${t##*.}
仅返回$t
。
我将让您决定要在哪里使用tfrac
。也许像
printf "%d.%s seconds" $s $tfrac
(不要使用%d.%d
,它会删除前导零,例如123.05
会变成123.5
)
或者,采用以下12d 1h 14m 17.912s
格式:
converts() {
t=$1
case $t in
*.*) tfrac=${t##*.} # fractional seconds
t=${t%%.*} # full seconds
;;
*) tfrac=0 # no decimal point
;;
esac
d=$((t/60/60/24))
h=$((t/60/60%24))
m=$((t/60%60))
s=$((t%60))
printf "%dd %dh %dm %d.%ss\n" "$d" "$h" "$m" "$s" "$tfrac"
}
和
$ converts $(( 1*86400 + 23*3600 + 45*60 + 6)).987
1d 23h 45m 6.987s