사람이 읽을 수 있는(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와 유사한 모든 쉘에서 작동합니다(일부 고대 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
정수가 한 자리 숫자인 경우 정수 앞에 0을 붙인다는 것을 나타냅니다. %06.3f
가장 이상한 점은 소수점 이하 3자리를 의미하며, 전체 길이가 6(소수점 포함)보다 작으면 앞에 0이 추가된다는 것입니다.
의도적으로 인용되지 않은 $(…)
대체는 다음을 사용하여 다음 세 가지 매개변수를 제공합니다 dc
.
먼저 $seconds
(확장된 숫자)를 스택에 푸시한 다음 3600으로 나누어 시간을 구합니다. 그것을 팝업하여 인쇄한 다음 공백을 밀어서 인쇄합니다( [ ] n
).
스택에는 초만 남았습니다. 복사하여 60으로 나눕니다(다시 잘림). 시간을 버리려면 모드 60이 필요합니다. 공백을 다시 추가하여 인쇄하십시오. 스택에는 초만 남습니다.
마지막으로, mod 60은 초 필드만 제공합니다. DC에서는 모듈러스가 소수에 완벽하고 정밀도를 유지합니다. f
그런 다음 스택과 개행 문자를 인쇄합니다.
답변3
간단한 sh로 쉽게 할 수 있습니다. GNU 날짜를 사용하여 코드를 약간 더 짧게 만들 수 있습니다(밀리초 단위로 반올림해도 괜찮기를 바랍니다. 가장 가까운 값으로 반올림하면 코드가 약간 길어집니다).
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