如何将秒转换为日/小时/分钟/秒

如何将秒转换为日/小时/分钟/秒

我正在尝试将这个时间格式翻译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

相关内容