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"
편집: 죄송합니다. 이는 적어도 세 가지 측면에서 문제가 있습니다. 으로 테스트해봤습니다 3707.001234
.
(1) 기준이 1970-01-이므로 날짜에 일회성 오류가 있습니다.01.
(2) 바로 볼 수 없는 시간에 일회성 오류가 있습니다(GMT 기준인데 시간대가 유력한 용의자입니다). date -d @0
보고서 Thu 1 Jan 01:00:00 BST 1970
도요. 1월의 BST? ? ?
(3) 위의 간격은 2678400
한 달 전체를 삭제합니다.
까다로운 건, 이 날짜들이에요. 나는 매우 미안 해요. 그러나 1초의 몇 분의 1초를 처리하는 방법은 정확합니다. 구문 분석하고 부분 문자열을 지정하는 것입니다.
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
. 선행 0이 제거됩니다. 예 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