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
区切り文字を使用して値を配列に分割します.
。
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"
編集:申し訳ありません。これは少なくとも3つの点で問題があります。でテストしてみました3707.001234
。
(1) 基準は 1970-01- であるため、日付に 1 回限りのエラーがあります。01。
(2)すぐに見えない時間に1回限りのエラーがあります(GMT基準ですが、時間帯が有力な容疑者です)。date -d @0
レポートトヨThu 1 Jan 01:00:00 BST 1970
。 1月のBST? ? ?
(3)上記の間隔は、2678400
1ヶ月全体を削除します。
難しいのは、これらの日付です。とても申し訳ありません。ただし、1秒の数分の1秒を処理する方法は正確です。解析して部分文字列を指定することです。
Googleの付録:BSTとイギリスの実験
英国サマータイム(BST)は、1968年2月から1971年10月まで、年間を通して適用されます。
答え2
時間の小数部の場合、値は拡張を使用して分割できます${var##prefix}
。${var%%suffix}
値から最も長い一致プレフィックスとサフィックスを削除します$var
。
だから、2行のコメントが追加されました。
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