bash 스크립트에서 경과 된 시간을 계산하는 방법은 무엇입니까?


224

를 사용하여 시작 및 종료 시간을 인쇄하면 date +"%T"다음과 같은 결과가 나타납니다.

10:33:56
10:36:10

이 두 가지의 차이점을 어떻게 계산하고 인쇄 할 수 있습니까?

나는 다음과 같은 것을 얻고 싶다 :

2m 14s

5
다른 말로, time명령을 사용할 수 없습니까?
anishsane

대신 유닉스 시간을 사용하고 date +%s빼기 (초)를 얻으십시오.
roblogic April

답변:


476

Bash에는 SECONDS셸이 시작된 후 경과 한 시간 (초)을 추적 하는 편리한 내장 변수가 있습니다. 이 변수는 할당 될 때 속성을 유지하며 할당 후 반환 된 값은 할당 이후의 시간 (초)에 할당 된 값을 더한 값입니다.

따라서 SECONDS시간이 지정된 이벤트를 시작하기 전에 0으로 설정 하고 이벤트를 읽은 SECONDS후 표시하기 전에 시간을 산술 할 수 있습니다.

SECONDS=0
# do some work
duration=$SECONDS
echo "$(($duration / 60)) minutes and $(($duration % 60)) seconds elapsed."

이 솔루션은 date +%sGNU 확장 에 의존하지 않기 때문에 Bash가 지원하는 모든 시스템에 이식 가능합니다.


59
+1. 또한 date을 작성하여 시간 산술을 수행하도록 속일 수 있습니다 date -u -d @"$diff" +'%-Mm %-Ss'. (이것은 $diff초 이후로 해석 되며 UTC로 분과 초를 계산합니다.) 아마 더 화려하지는 않을 것입니다. - P
ruakh

13
좋고 간단합니다. 누군가 시간이 필요한 경우 :echo "$(($diff / 3600)) hours, $((($diff / 60) % 60)) minutes and $(($diff % 60)) seconds elapsed."
chus

6
$(date -u +%s)일광 절약 시간 제가 전환 된 날짜의 경쟁 조건을 방지하기 위해 읽어야 합니다. 악의 도약 초를 조심하십시오;)
Tino

3
@ daniel-kamil-kozar 만나서 반갑습니다. 그러나 이것은 약간 깨지기 쉽습니다. 그러한 변수는 하나뿐이므로 재귀 적으로 성능을 측정하는 데 사용될 수 없으며, 그 후에 unset SECONDS는 더 나빠질 수도 있습니다 .echo $SECONDS; unset SECONDS; SECONDS=0; sleep 3; echo $SECONDS
Tino

6
@ParthianShot : 그렇게 생각해서 죄송합니다. 그러나이 답변은 대부분의 사람들이 다음과 같은 질문에 대한 답변을 검색하는 동안 필요한 것입니다.
Daniel Kamil Kozar

99

경과 시간 (초)을 측정하려면 다음이 필요합니다.

  • 경과 된 초 수를 나타내는 정수
  • 이러한 정수를 사용 가능한 형식으로 변환하는 방법.

경과 된 초의 정수 값 :

  • 경과 된 초 수의 정수 값을 찾는 두 가지 bash 내부 방법이 있습니다.

    1. 배쉬 변수 SECONDS (SECONDS가 설정되어 있지 않으면 특수 속성이 손실 됨)

      • SECONDS 값을 0으로 설정 :

        SECONDS=0
        sleep 1  # Process to execute
        elapsedseconds=$SECONDS
      • SECONDS시작시 변수 값 저장 :

        a=$SECONDS
        sleep 1  # Process to execute
        elapsedseconds=$(( SECONDS - a ))
    2. Bash printf 옵션 %(datefmt)T:

      a="$(TZ=UTC0 printf '%(%s)T\n' '-1')"    ### `-1`  is the current time
      sleep 1                                  ### Process to execute
      elapsedseconds=$(( $(TZ=UTC0 printf '%(%s)T\n' '-1') - a ))

이러한 정수를 사용 가능한 형식으로 변환

bash internal printf은 직접 수행 할 수 있습니다.

$ TZ=UTC0 printf '%(%H:%M:%S)T\n' 12345
03:25:45

비슷하게

$ elapsedseconds=$((12*60+34))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
00:12:34

그러나 실제로는 실제 시간이 아닌 벽시계 시간을 인쇄하므로 24 시간 이상 지속되지 않습니다.

$ hours=30;mins=12;secs=24
$ elapsedseconds=$(( ((($hours*60)+$mins)*60)+$secs ))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
06:12:24

bash-hackers.org 에서 세부 사항을 좋아하는 사람들을 위해 :

%(FORMAT)TFORMAT을 형식 문자열로 사용하여 생성 된 날짜-시간 문자열을 출력합니다 strftime(3). 연관된 인수는 Epoch 이후의 시간 (초 ) 또는 -1 (현재 시간) 또는 -2 (쉘 시작 시간)입니다. 해당 인수가 제공되지 않으면 현재 시간이 기본값으로 사용됩니다.

따라서 또 다른 지속 시간 인쇄 구현이 textifyDuration $elpasedseconds있는 곳을 호출하고 싶을 수도 있습니다 textifyDuration.

textifyDuration() {
   local duration=$1
   local shiff=$duration
   local secs=$((shiff % 60));  shiff=$((shiff / 60));
   local mins=$((shiff % 60));  shiff=$((shiff / 60));
   local hours=$shiff
   local splur; if [ $secs  -eq 1 ]; then splur=''; else splur='s'; fi
   local mplur; if [ $mins  -eq 1 ]; then mplur=''; else mplur='s'; fi
   local hplur; if [ $hours -eq 1 ]; then hplur=''; else hplur='s'; fi
   if [[ $hours -gt 0 ]]; then
      txt="$hours hour$hplur, $mins minute$mplur, $secs second$splur"
   elif [[ $mins -gt 0 ]]; then
      txt="$mins minute$mplur, $secs second$splur"
   else
      txt="$secs second$splur"
   fi
   echo "$txt (from $duration seconds)"
}

GNU 날짜.

형식화 된 시간을 얻으려면 몇 가지 방법으로 외부 도구 (GNU 날짜)를 사용하여 거의 1 년 길이까지 나노초를 포함해야합니다.

날짜 안에 수학.

외부 산술이 필요하지 않습니다. 한 번에 한 단계 만 수행하십시오 date.

date -u -d "0 $FinalDate seconds - $StartDate seconds" +"%H:%M:%S"

예, 0명령 문자열에 0이 있습니다. 필요합니다.

즉, date +"%T"명령을 명령으로 변경 date +"%s"하여 값을 초 단위로 저장 (인쇄) 할 수 있다고 가정합니다 .

명령은 다음으로 제한됩니다.

  • $StartDate$FinalDate초의 양수 값
  • 의 값 $FinalDate이 (보다 늦음)보다 큽니다 $StartDate.
  • 24 시간보다 작은 시차.
  • 시간, 분 및 초가있는 출력 형식을 승인합니다. 변경하기 매우 쉽습니다.
  • -u UTC 시간을 사용할 수 있습니다. "DST"및 현지 시간 수정을 피합니다.

문자열 을 사용해야 하는 경우 10:33:56초로 변환하면 초라
는 단어가 sec로 축약 될 수 있습니다.

string1="10:33:56"
string2="10:36:10"
StartDate=$(date -u -d "$string1" +"%s")
FinalDate=$(date -u -d "$string2" +"%s")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S"

위에서 설명한 초 시간 변환은 "오늘"오늘의 시작 (오늘)과 관련이 있습니다.


이 개념은 다음과 같이 나노초로 확장 될 수 있습니다.

string1="10:33:56.5400022"
string2="10:36:10.8800056"
StartDate=$(date -u -d "$string1" +"%s.%N")
FinalDate=$(date -u -d "$string2" +"%s.%N")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S.%N"

더 긴 (최대 364 일) 시간 차이를 계산해야하는 경우 (일부) 연도를 참조로 사용하고 형식 값 %j( 연도의 일수)을 사용해야합니다 .

비슷하다:

string1="+10 days 10:33:56.5400022"
string2="+35 days 10:36:10.8800056"
StartDate=$(date -u -d "2000/1/1 $string1" +"%s.%N")
FinalDate=$(date -u -d "2000/1/1 $string2" +"%s.%N")
date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N"

Output:
026 days 00:02:14.340003400

안타깝게도이 경우 1일 수에서 ONE 을 수동으로 빼야 합니다. 날짜 명령은 연중 첫날을 1로 간주합니다. 그렇게 어렵지 않습니다 ...

a=( $(date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N") )
a[0]=$((10#${a[0]}-1)); echo "${a[@]}"



https://www.gnu.org/software/coreutils/manual/html_node/Examples-of-date.html#Examples-of-date 는 긴 초 단위의 사용이 유효하고 문서화되어 있습니다.


비지 박스 날짜

더 작은 장치 (설치할 아주 작은 실행 파일)에 사용되는 도구 : Busybox.

다음과 같이 busybox에 링크를 작성하십시오.

$ ln -s /bin/busybox date

그런 다음 이것을 호출하여 사용하십시오 date(PATH 포함 디렉토리에 배치).

또는 다음과 같은 별칭을 만드십시오.

$ alias date='busybox date'

Busybox 날짜에는 좋은 옵션이 있습니다. -D는 입력 시간 형식을 수신합니다. 그것은 시간으로 사용될 많은 형식을 엽니 다. -D 옵션을 사용하면 시간 10:33:56을 직접 변환 할 수 있습니다.

date -D "%H:%M:%S" -d "10:33:56" +"%Y.%m.%d-%H:%M:%S"

위 명령의 결과에서 볼 수 있듯이 그 날은 "오늘"인 것으로 가정합니다. 에포크에서 시작하는 시간을 얻으려면 :

$ string1="10:33:56"
$ date -u -D "%Y.%m.%d-%H:%M:%S" -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56

Busybox 날짜는 -D 없이도 시간을 수신 할 수 있습니다 (위 형식).

$ date -u -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56

그리고 출력 형식은 에포크 이후 몇 초가 될 수도 있습니다.

$ date -u -d "1970.01.01-$string1" +"%s"
52436

두 경우 모두 약간의 bash 수학 (busybox는 아직 수학을 수행 할 수 없음) :

string1="10:33:56"
string2="10:36:10"
t1=$(date -u -d "1970.01.01-$string1" +"%s")
t2=$(date -u -d "1970.01.01-$string2" +"%s")
echo $(( t2 - t1 ))

또는 형식 :

$ date -u -D "%s" -d "$(( t2 - t1 ))" +"%H:%M:%S"
00:02:14

6
이것은 많은 기초와 훌륭한 설명으로 이루어진 놀라운 대답입니다. 감사합니다!
Devy

bash에 통합 된 명령에 %(FORMAT)T전달 된 문자열 을 찾아야했습니다 printf. 에서 bash-hackers.org을 : %(FORMAT)T출력 일시 문자열을 사용하는 결과 FORMAT의 strftime (3)의 형식 문자열로. 연관된 인수는 Epoch 이후의 시간 (초) 또는 -1 (현재 시간) 또는 -2 (쉘 시작 시간)입니다. 해당 인수가 제공되지 않으면 현재 시간이 기본값으로 사용됩니다 . 비의입니다. 이 경우, "에포크 이후의 초 수"가 %s주어진다 strftime(3).
David Tonhofer

35

내가 한 방법은 다음과 같습니다.

START=$(date +%s);
sleep 1; # Your stuff
END=$(date +%s);
echo $((END-START)) | awk '{print int($1/60)":"int($1%60)}'

정말 간단합니다. 시작 시간 (초)을 마친 다음 끝 시간 (초)을 가져 와서 분 : 초 단위로 차이를 인쇄합니다.


6
내 솔루션과 다른 점은 무엇입니까? awkBash는 정수 산술을 똑같이 잘 처리하기 때문에이 경우 호출의 이점을 실제로 볼 수 없습니다 .
Daniel Kamil Kozar

1
당신의 대답도 정확합니다. 나와 같은 일부 사람들은 bash 불일치보다 awk로 작업하는 것을 선호합니다.
도리안

2
정수 산술과 관련하여 Bash의 불일치에 대해 좀 더 자세히 설명해 주시겠습니까? 나는 아무것도 알지 못했기 때문에 이것에 대해 더 알고 싶습니다.
Daniel Kamil Kozar

12
나는 이것을 찾고 있었다. 이 답변에 대한 비판을 이해하지 못합니다. 문제에 대한 솔루션을 두 개 이상보고 싶습니다. 그리고 나는 awkbash 보다 명령을 선호하는 사람입니다 (awk는 다른 쉘에서 작동하기 때문에 아무것도 없다면). 이 솔루션이 더 좋았습니다. 그러나 그것은 나의 개인적인 의견입니다.
rpsml

4
선행 0 : echo $ ((END-START)) | awk '{printf "% 02d : % 02d \ n", int ($ 1 / 60), int ($ 1 % 60)}'
Jon Strayer

17

다른 옵션은 ( http://www.fresse.org/dateutils/#datediff ) datediff에서 사용하는 것 입니다 .dateutils

$ datediff 10:33:56 10:36:10
134s
$ datediff 10:33:56 10:36:10 -f%H:%M:%S
0:2:14
$ datediff 10:33:56 10:36:10 -f%0H:%0M:%0S
00:02:14

당신은 또한 사용할 수 있습니다 gawk. mawk1.3.4 또한이 strftimemktime의 있지만 이전 버전 mawk과는 nawk하지 않습니다.

$ TZ=UTC0 awk 'BEGIN{print strftime("%T",mktime("1970 1 1 10 36 10")-mktime("1970 1 1 10 33 56"))}'
00:02:14

또는 GNU로 다른 방법을 사용할 수 있습니다 date.

$ date -ud@$(($(date -ud'1970-01-01 10:36:10' +%s)-$(date -ud'1970-01-01 10:33:56' +%s))) +%T
00:02:14

1
나는 당신의 GNU date 방법 과 같은 것을 찾고있었습니다 . 천재.
Haohmaru

내 의견을 삭제하십시오 ... 죄송합니다
빌 게일

dateutilsapt 를 통해 설치 한 후 datediff사용할 명령 이 없었 습니다 dateutils.ddiff.
수 자나

12

나는 date명령을 회상하지 않는 다른 방법을 제안하고 싶습니다 . 이미 %T날짜 형식으로 타임 스탬프를 수집 한 경우 도움이 될 수 있습니다 .

ts_get_sec()
{
  read -r h m s <<< $(echo $1 | tr ':' ' ' )
  echo $(((h*60*60)+(m*60)+s))
}

start_ts=10:33:56
stop_ts=10:36:10

START=$(ts_get_sec $start_ts)
STOP=$(ts_get_sec $stop_ts)
DIFF=$((STOP-START))

echo "$((DIFF/60))m $((DIFF%60))s"

같은 방법으로 밀리 초를 처리 할 수도 있습니다.

ts_get_msec()
{
  read -r h m s ms <<< $(echo $1 | tr '.:' ' ' )
  echo $(((h*60*60*1000)+(m*60*1000)+(s*1000)+ms))
}

start_ts=10:33:56.104
stop_ts=10:36:10.102

START=$(ts_get_msec $start_ts)
STOP=$(ts_get_msec $stop_ts)
DIFF=$((STOP-START))

min=$((DIFF/(60*1000)))
sec=$(((DIFF%(60*1000))/1000))
ms=$(((DIFF%(60*1000))%1000))

echo "${min}:${sec}.$ms"

1
10 예 핸들 millisecons 수있는 방법이 있나요 : 33 : 56.104
Umesh Rajbhandari

밀리 초 필드가 0으로 시작하면 밀리 초 처리가 잘못 작동합니다. 예를 들어 ms 필드는 8 진수로 해석되므로 ms = "033"은 "027"의 후행 숫자를 제공합니다. "echo"... "+ ms))"를 ... "+ $ {ms ## + (0)}))"로 변경하면 "shopt -s extglob"이 위의 어딘가에있는 한이 문제가 해결됩니다. 스크립트. 아마도 h, m, s에서 선행 0을 제거해야합니다.
Eric Towers

3
echo $(((60*60*$((10#$h)))+(60*$((10#$m)))+$((10#$s))))내가 도착한 이래로 나를 위해 일했다value too great for base (error token is "08")
Niklas

6

여기 마술이 있습니다 :

time1=14:30
time2=$( date +%H:%M ) # 16:00
diff=$(  echo "$time2 - $time1"  | sed 's%:%+(1/60)*%g' | bc -l )
echo $diff hours
# outputs 1.5 hours

seda :를 1/60으로 변환 할 수식으로 바꿉니다 . 그런 다음에 의해 만들어진 시간 계산bc


5

현재 날짜 (GNU coreutils) 7.4 -d를 사용하여 산술을 수행 할 수 있습니다.

$ date -d -30days
Sat Jun 28 13:36:35 UTC 2014

$ date -d tomorrow
Tue Jul 29 13:40:55 UTC 2014

사용할 수있는 단위는 일, 년, 월, 시간, 분 및 초입니다.

$ date -d tomorrow+2days-10minutes
Thu Jul 31 13:33:02 UTC 2014

3

Daniel Kamil Kozar의 답변에 따라 시간 / 분 / 초를 표시하십시오.

echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds"

따라서 전체 스크립트는 다음과 같습니다.

date1=$(date +"%s")
date2=$(date +"%s")
diff=$(($date2-$date1))
echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds"

3

아니면 조금 마무리

alias timerstart='starttime=$(date +"%s")'
alias timerstop='echo seconds=$(($(date +"%s")-$starttime))'

그런 다음 작동합니다.

timerstart; sleep 2; timerstop
seconds=2

3

다음은 date완료 시간을 저장하기 위해 두 번째 변수를 사용하지 않고 "ago"를 사용 하는 명령 기능 만 사용하는 솔루션입니다 .

#!/bin/bash

# save the current time
start_time=$( date +%s.%N )

# tested program
sleep 1

# the current time after the program has finished
# minus the time when we started, in seconds.nanoseconds
elapsed_time=$( date +%s.%N --date="$start_time seconds ago" )

echo elapsed_time: $elapsed_time

이것은 다음을 제공합니다.

$ ./time_elapsed.sh 
elapsed_time: 1.002257120

2
% start=$(date +%s)
% echo "Diff: $(date -d @$(($(date +%s)-$start)) +"%M minutes %S seconds")"
Diff: 00 minutes 11 seconds

6
이 답변의 기능이 다른 답변의 기능과 다름을 아는 것이 도움이 될 것입니다.
Louis

를 통해 허용되는 모든 형식으로 지속 시간을 쉽게 출력 할 수 있습니다 date.
Ryan C. Thompson

2

date 차이점을 제시하고 형식을 지정할 수 있습니다 (표시된 OS X 옵션).

date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) +%T
# 00:02:14

date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) \
    +'%-Hh %-Mm %-Ss'
# 0h 2m 14s

일부 문자열 처리는 빈 값을 제거 할 수 있습니다

date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) \
    +'%-Hh %-Mm %-Ss' | sed "s/[[:<:]]0[hms] *//g"
# 2m 14s

이전 시간을 먼저 배치하면 작동하지 않습니다. 처리해야 할 경우 다음으로 변경하십시오 $(($(date ...) - $(date ...))).$(echo $(date ...) - $(date ...) | bc | tr -d -)


1

함께 사용할 시차 스크립트가 필요했으며 mencoder( --endpos상대적) 내 솔루션은 Python 스크립트를 호출하는 것입니다.

$ ./timediff.py 1:10:15 2:12:44
1:02:29

초 단위도 지원됩니다.

$ echo "diff is `./timediff.py 10:51.6 12:44` (in hh:mm:ss format)"
diff is 0:01:52.4 (in hh:mm:ss format)

200과 120의 차이가 1 시간 20 분이라는 것을 알 수 있습니다.

$ ./timediff.py 120:0 200:0
1:20:0

초 또는 분 또는 시간 (아마도 분수)을 hh : mm : ss로 변환 할 수 있습니다.

$ ./timediff.py 0 3600
1:00:0
$ ./timediff.py 0 3.25:0:0
3:15:0

timediff.py :

#!/usr/bin/python

import sys

def x60(h,m):
    return 60*float(h)+float(m)

def seconds(time):
    try:
       h,m,s = time.split(':')
       return x60(x60(h,m),s)
    except ValueError:
       try:
          m,s = time.split(':')
          return x60(m,s)
       except ValueError:
          return float(time)

def difftime(start, end):
    d = seconds(end) - seconds(start)
    print '%d:%02d:%s' % (d/3600,d/60%60,('%02f' % (d%60)).rstrip('0').rstrip('.'))

if __name__ == "__main__":
   difftime(sys.argv[1],sys.argv[2])

1

GNU로 units:

$ units
2411 units, 71 prefixes, 33 nonlinear units
You have: (10hr+36min+10s)-(10hr+33min+56s)
You want: s
    * 134
    / 0.0074626866
You have: (10hr+36min+10s)-(10hr+33min+56s)
You want: min
    * 2.2333333
    / 0.44776119

1

GNU 날짜를 사용하여 @nisetama 솔루션 일반화 (신뢰할 수있는 Ubuntu 14.04 LTS) :

start=`date`
# <processing code>
stop=`date`
duration=`date -ud@$(($(date -ud"$stop" +%s)-$(date -ud"$start" +%s))) +%T`

echo $start
echo $stop
echo $duration

굽힐 수 있는:

Wed Feb 7 12:31:16 CST 2018
Wed Feb 7 12:32:25 CST 2018
00:01:09

1
#!/bin/bash

START_TIME=$(date +%s)

sleep 4

echo "Total time elapsed: $(date -ud "@$(($(date +%s) - $START_TIME))" +%T) (HH:MM:SS)"
$ ./total_time_elapsed.sh 
Total time elapsed: 00:00:04 (HH:MM:SS)

1

이 함수를 정의하십시오 (예 : ~ / .bashrc) :

time::clock() {
    [ -z "$ts" ]&&{ ts=`date +%s%N`;return;}||te=`date +%s%N`
    printf "%6.4f" $(echo $((te-ts))/1000000000 | bc -l)
    unset ts te
}

이제 스크립트의 일부 시간을 측정 할 수 있습니다.

$ cat script.sh
# ... code ...
time::clock
sleep 0.5
echo "Total time: ${time::clock}"
# ... more code ...

$ ./script.sh
Total time: 0.5060

실행 병목 현상을 찾는 데 매우 유용합니다.


0

나는 이것이 오래된 게시물이라는 것을 알고 있지만 오늘 로그 파일에서 날짜와 시간을 가져와 델타를 계산하는 스크립트를 작성하면서 그것을 보았습니다. 아래 스크립트는 확실히 과잉이므로 논리와 수학을 확인하는 것이 좋습니다.

#!/bin/bash

dTime=""
tmp=""

#firstEntry="$(head -n 1 "$LOG" | sed 's/.*] \([0-9: -]\+\).*/\1/')"
firstEntry="2013-01-16 01:56:37"
#lastEntry="$(tac "$LOG" | head -n 1 | sed 's/.*] \([0-9: -]\+\).*/\1/')"
lastEntry="2014-09-17 18:24:02"

# I like to make the variables easier to parse
firstEntry="${firstEntry//-/ }"
lastEntry="${lastEntry//-/ }"
firstEntry="${firstEntry//:/ }"
lastEntry="${lastEntry//:/ }"

# remove the following lines in production
echo "$lastEntry"
echo "$firstEntry"

# compute days in last entry
for i in `seq 1 $(echo $lastEntry|awk '{print $2}')`; do {
  case "$i" in
   1|3|5|7|8|10|12 )
    dTime=$(($dTime+31))
    ;;
   4|6|9|11 )
    dTime=$(($dTime+30))
    ;;
   2 )
    dTime=$(($dTime+28))
    ;;
  esac
} done

# do leap year calculations for all years between first and last entry
for i in `seq $(echo $firstEntry|awk '{print $1}') $(echo $lastEntry|awk '{print $1}')`; do {
  if [ $(($i%4)) -eq 0 ] && [ $(($i%100)) -eq 0 ] && [ $(($i%400)) -eq 0 ]; then {
    if [ "$i" = "$(echo $firstEntry|awk '{print $1}')" ] && [ $(echo $firstEntry|awk '{print $2}') -lt 2 ]; then {
      dTime=$(($dTime+1))
    } elif [ $(echo $firstEntry|awk '{print $2}') -eq 2 ] && [ $(echo $firstEntry|awk '{print $3}') -lt 29 ]; then {
      dTime=$(($dTime+1))
    } fi
  } elif [ $(($i%4)) -eq 0 ] && [ $(($i%100)) -ne 0 ]; then {
    if [ "$i" = "$(echo $lastEntry|awk '{print $1}')" ] && [ $(echo $lastEntry|awk '{print $2}') -gt 2 ]; then {
      dTime=$(($dTime+1))
    } elif [ $(echo $lastEntry|awk '{print $2}') -eq 2 ] && [ $(echo $lastEntry|awk '{print $3}') -ne 29 ]; then {
      dTime=$(($dTime+1))
    } fi
  } fi
} done

# substract days in first entry
for i in `seq 1 $(echo $firstEntry|awk '{print $2}')`; do {
  case "$i" in
   1|3|5|7|8|10|12 )
    dTime=$(($dTime-31))
    ;;
   4|6|9|11 )
    dTime=$(($dTime-30))
    ;;
   2 )
    dTime=$(($dTime-28))
    ;;
  esac
} done

dTime=$(($dTime+$(echo $lastEntry|awk '{print $3}')-$(echo $firstEntry|awk '{print $3}')))

# The above gives number of days for sample. Now we need hours, minutes, and seconds
# As a bit of hackery I just put the stuff in the best order for use in a for loop
dTime="$(($(echo $lastEntry|awk '{print $6}')-$(echo $firstEntry|awk '{print $6}'))) $(($(echo $lastEntry|awk '{print $5}')-$(echo $firstEntry|awk '{print $5}'))) $(($(echo $lastEntry|awk '{print $4}')-$(echo $firstEntry|awk '{print $4}'))) $dTime"
tmp=1
for i in $dTime; do {
  if [ $i -lt 0 ]; then {
    case "$tmp" in
     1 )
      tmp="$(($(echo $dTime|awk '{print $1}')+60)) $(($(echo $dTime|awk '{print $2}')-1))"
      dTime="$tmp $(echo $dTime|awk '{print $3" "$4}')"
      tmp=1
      ;;
     2 )
      tmp="$(($(echo $dTime|awk '{print $2}')+60)) $(($(echo $dTime|awk '{print $3}')-1))"
      dTime="$(echo $dTime|awk '{print $1}') $tmp $(echo $dTime|awk '{print $4}')"
      tmp=2
      ;;
     3 )
      tmp="$(($(echo $dTime|awk '{print $3}')+24)) $(($(echo $dTime|awk '{print $4}')-1))"
      dTime="$(echo $dTime|awk '{print $1" "$2}') $tmp"
      tmp=3
      ;;
    esac
  } fi
  tmp=$(($tmp+1))
} done

echo "The sample time is $(echo $dTime|awk '{print $4}') days, $(echo $dTime|awk '{print $3}') hours, $(echo $dTime|awk '{print $2}') minutes, and $(echo $dTime|awk '{print $1}') seconds."

다음과 같이 출력됩니다.

2012 10 16 01 56 37
2014 09 17 18 24 02
The sample time is 700 days, 16 hours, 27 minutes, and 25 seconds.

스크립트를 독립형으로 만들기 위해 조금 수정했습니다 (예 : 변수 값 설정). 그러나 일반적인 아이디어도 나옵니다. 음수 값을 확인하는 데 추가 오류가 필요할 수 있습니다.


Gee, 많은 일 !!. 내 대답을보십시오 : stackoverflow.com/a/24996647/2350426

0

mcaleaa의 답변에 대해서는 언급 할 수 없으므로 여기에 게시하십시오. "diff"변수는 대소 문자를 사용해야합니다. 다음은 예입니다.

[root@test ~]# date1=$(date +"%s"); date
Wed Feb 21 23:00:20 MYT 2018
[root@test ~]# 
[root@test ~]# date2=$(date +"%s"); date
Wed Feb 21 23:00:33 MYT 2018
[root@test ~]# 
[root@test ~]# diff=$(($date2-$date1))
[root@test ~]# 

이전 변수는 소문자로 선언되었습니다. 대문자를 사용했을 때 일어난 일입니다.

[root@test ~]# echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds"
-bash: / 3600 : syntax error: operand expected (error token is "/ 3600 ")
[root@test ~]# 

따라서 빠른 수정은 다음과 같습니다.

[root@test ~]# echo "Duration: $(($diff / 3600 )) hours $((($diff % 3600) / 60)) minutes $(($diff % 60)) seconds"
Duration: 0 hours 0 minutes 13 seconds
[root@test ~]# 

-1

여기 내 bash 구현이 있습니다 (다른 SO에서 가져온 비트;;)

function countTimeDiff() {
    timeA=$1 # 09:59:35
    timeB=$2 # 17:32:55

    # feeding variables by using read and splitting with IFS
    IFS=: read ah am as <<< "$timeA"
    IFS=: read bh bm bs <<< "$timeB"

    # Convert hours to minutes.
    # The 10# is there to avoid errors with leading zeros
    # by telling bash that we use base 10
    secondsA=$((10#$ah*60*60 + 10#$am*60 + 10#$as))
    secondsB=$((10#$bh*60*60 + 10#$bm*60 + 10#$bs))
    DIFF_SEC=$((secondsB - secondsA))
    echo "The difference is $DIFF_SEC seconds.";

    SEC=$(($DIFF_SEC%60))
    MIN=$((($DIFF_SEC-$SEC)%3600/60))
    HRS=$((($DIFF_SEC-$MIN*60)/3600))
    TIME_DIFF="$HRS:$MIN:$SEC";
    echo $TIME_DIFF;
}

$ countTimeDiff 2:15:55 2:55:16
The difference is 2361 seconds.
0:39:21

테스트되지 않았으며 버그가있을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.