초를 일/시/분/초로 변환하는 방법

초를 일/시/분/초로 변환하는 방법

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

관련 정보