
我有一個時間間隔(以秒為單位,帶小數),我想以人類可讀的(H:MM:SS.SSS)格式顯示。例如,16633.284 應顯示為 4:37:13.284。所有這些時間都在 24 小時以內,但如果超過了,也只是幾個小時而已。
再舉幾個例子:
0 → 0:00:00.000
60.394 → 0:01:00.394
8944.77 → 2:29:04.770
請注意,它在 10 小時內是固定寬度的。當然,使用 可以輕鬆做到這一點printf
。
我將我的解決方案作為答案發布,但感覺必須有更好的方法來做到這一點,所以我問:還有其他方法嗎?我對 bashisms、zshisms 等方式持開放態度。
註:這與將秒顯示為天/小時/分鐘/秒?但這些方法都不起作用,因為 bash 中的算術僅是整數。
答案1
小數部分對小時數、分鐘數或秒數沒有任何貢獻,因此您可以簡單地將其放在一邊,在沒有它的情況下進行計算,然後將其添加到末尾。像這樣的東西:
#!/bin/sh
seconds=16633.284
f=${seconds##*.}
if [ "$f" = "$seconds" ]; then f=0; fi
t=${seconds%.*}
s=$((t%60))
m=$((t/60%60))
h=$((t/60/60))
printf '%d:%02d:%06.3f\n' $h $m $s.$f
輸出:
0 → 0:00:00.000
33. → 0:00:33.000
.21 → 0:00:00.210
60.394 → 0:01:00.394
8944.77 → 2:29:04.770
這適用於任何類似 sh 的 shell(除了一些古老的 POSIX 之前的 shell)。
答案2
我的方法是這樣的,用來dc
計算:
seconds=16633.284
printf '%i:%02i:%06.3f\n' \
$(dc -e "$seconds d 3600 / n [ ] n d 60 / 60 % n [ ] n 60 % f")
希望 printf 很熟悉,但如果不熟悉,%i
則表示一個整數。%02i
表示如果整數是個位數,則用前導 0 填滿該整數。%06.3f
最奇怪的是,它的意思是小數點後3位,如果總長度小於6(包括小數點)則用前導0填滿。
故意不帶引號的$(…)
替換給出了這三個參數,使用dc
:
首先,將$seconds
(展開後的數字)壓入堆疊;複製它;然後除以(截斷)3600 即可得到小時數。彈出並列印該內容,然後推入空格並列印它 ( [ ] n
)。
堆疊上只剩下秒了。複製它,除以 60(再次截斷)。這給了分鐘;採取 mod 60 來丟棄小時數。列印出來,再次加上空格。只在堆疊上留下秒數。
最後,mod 60 只給出秒字段,在直流中,模數非常適合小數並保留精度。f
然後列印堆疊加上換行符。
答案3
您可以輕鬆地用簡單的 sh 完成它。您可以使用 GNU date 使程式碼稍微短一些(希望您不介意向下捨入毫秒,四捨五入到最接近的值會稍微長一些):
hours=$((${seconds%.*} / 3600))
min_s_nano=$(TZ=GMT date -d @$seconds +%M:%S.%N)
time_string=$hours:${min_s_nano%??????}
答案4
我們呼叫dc
秒數並將其放入堆疊中,然後執行計算(秒->HH/MM/SS.MSEC)、格式化並顯示結果。
seconds=16633.284
dc <<DC
# rearrange stack for number < 1hr
[r ldx q]sb
# rearrange stack for number < 1min
[rd ldxq]sc
# min++, sec-=60 hrs++, min-=60
[r1+r 60-d 60!>a]sa
# display result as h:mm:ss.sss
[n 58an 2lpx 58an 2lpx 46an 3lpx 10an]sd
# perform the conversion of seconds -> hours, minutes, seconds
[d60 >c lax r0rd60 >b lax r ldx]si
[
d1000* 1000% 1/r # fractional portion
1000* 1000/ 1/0r # integer portion
lix
]sh
# left zero-pad a number
[lk1+d sk 0n le >g ]sg
[sedZd sk le >gn]sp
# setup the number on the stack and begin computation
$seconds lhx
DC
結果
0 --> 0:00:00.000
60.394 --> 0:01:00.394
8944.77 --> 2:29:04.770
86399.99 --> 23:59:59.990
59.9999 --> 0:00:59.999
599.9999 --> 0:09:59.999
16633.284 --> 4:37:13.284
33 --> 0:00:33.000
.21 --> 0:00:00.210
123456789.123456 --> 34293:33:09.123