
人間が判読できる形式 (H:MM:SS.SSS) で表示したい、小数点付きの秒数単位の間隔があります。たとえば、16633.284 は 4:37:13.284 と表示されます。これらの時間はすべて 24 時間未満ですが、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 のようなシェル (POSIX 以前の古いシェルを除く) で動作します。
答え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
整数が 1 桁の場合、先頭に 0 を埋め込むことを意味します。%06.3f
は最も奇妙ですが、小数点の後に 3 桁を意味し、合計の長さが 6 (小数点を含む) 未満の場合は先頭に 0 を埋め込みます。
意図的に引用符で囲まれていない$(…)
置換により、次の 3 つのパラメータが提供されますdc
。
まず、$seconds
(拡張された、つまり実際の数値) をスタックにプッシュし、それを複製し、(切り捨てを使用して) 3600 で割って時間を取得します。それをポップして出力し、スペースをプッシュして出力します ( [ ] n
)。
すると、スタックには秒だけが残ります。これを複製し、60 で割ります (ここでも切り捨て)。これで分数が得られ、60 を法として時間を切り捨てます。これをスペース付きで出力します。スタックには秒だけが残ります。
最後に、秒フィールドのみを返す mod 60 を実行します。dc では、係数は小数点に完全に適合し、精度を維持します。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
秒数をスタックに配置し、計算 (secs->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