如何计算bash脚本中经过的时间?


224

我使用来打印开始时间和结束时间date +"%T",结果如下:

10:33:56
10:36:10

如何计算和打印这两者之间的差异?

我想得到类似的东西:

2m 14s

5
另一方面,您不能使用该time命令吗?
13年

改用unix时间date +%s,然后减去以获得秒数。
roblogic

Answers:


476

Bash有一个方便的SECONDS内置变量,可跟踪自启动外壳以来经过的秒数。该变量在分配时保留其属性,分配后返回的值是分配以来的秒数加上分配的值。

因此,您可以SECONDS在开始计时事件之前将其设置为0,在事件SECONDS之后进行读取,然后在显示之前进行时间算术运算。

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

由于此解决方案不依赖date +%s(这是GNU扩展),因此可以移植到Bash支持的所有系统中。


59
+1。顺便说一句,您可以date通过编写技巧为您执行时间算术date -u -d @"$diff" +'%-Mm %-Ss'。(这$diff自时间以来解释为秒,并以UTC计算分钟和秒。)不过,这可能并没有那么优雅,只是更好地模糊了。:-P
ruakh 2012年

13
漂亮又简单。如果有人需要几个小时:echo "$(($diff / 3600)) hours, $((($diff / 60) % 60)) minutes and $(($diff % 60)) seconds elapsed."
chus 2015年

6
应当阅读该内容,$(date -u +%s)以防止在切换夏令时的日期出现比赛情况。并注意邪恶的leap秒;)
蒂诺2015年

3
@ daniel-kamil-kozar很高兴找到。但是,这有点脆弱。只有一个这样的变量,因此它不能递归地用来衡量性能,甚至在unset SECONDS它消失之后甚至更糟:echo $SECONDS; unset SECONDS; SECONDS=0; sleep 3; echo $SECONDS
Tino 2015年

6
@ParthianShot:很抱歉您这么认为。但是,我相信这个答案是大多数人在寻找类似问题的答案时所需要的:测量事件之间经过的时间,而不是计算时间。
Daniel Kamil Kozar

99

要测量经过时间(以秒为单位),我们需要:

  • 一个整数,表示经过的秒数
  • 一种将此类整数转换为可用格式的方法。

经过的秒数的整数:

  • 有两种bash内部方法可以找到经过的秒数的整数值:

    1. Bash变量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内部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)T输出使用FORMAT作为的格式字符串得到的日期时间字符串strftime(3)。关联的参数是自Epoch以来的秒数,或者是-1(当前时间)或-2(shell启动时间)。如果未提供相应的参数,则将当前时间用作默认时间。

所以,你可能只想通话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日期)来获取将近一年的时间,包括纳秒。

日期内的数学。

无需外部运算,只需一步即可完成所有操作date

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

是的,0命令字符串中为零。这是必需的。

假设您可以将date +"%T"命令更改为命令,date +"%s"以便值将在几秒钟内存储(打印)。

请注意,该命令仅限于:

  • $StartDate$FinalDate秒的正值。
  • 中的值$FinalDate大于(较晚)$StartDate
  • 时差小于24小时。
  • 您接受带有小时,分钟和秒的输出格式。非常容易更改。
  • 可以使用-u UTC时间。避免“ DST”和本地时间更正。

如果必须使用该10:33:56字符串,那么只需将其转换为秒,
也可以将单词seconds缩写为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从天数中手动减去1 。date命令将一年的第一天视为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。

要么建立一个名为date的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

不带-D的Busybox日期甚至可以接收时间(采用上述格式):

$ 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 2016年

我必须查找%(FORMAT)T传递给printf集成在bash中的命令的字符串。从bash-hackers.org%(FORMAT)T输出日期时间字符串,该日期时间FORMAT字符串用作strftime(3)的格式字符串。关联的参数是自Epoch以来的秒数,或者是-1(当前时间)或-2(shell启动时间)。如果没有提供相应的自变量,则将当前时间用作默认值。太深奥了 在这种情况下,%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
与我的解决方案有什么不同?awk在这种情况下,我真的看不到调用带来的好处,因为Bash同样能很好地处理整数算术。
Daniel Kamil Kozar 2013年

1
您的答案也是正确的。和我一样,有些人更喜欢使用awk而不是bash不一致。
多里安

2
您能否详细说明一下Bash中与整数算术有关的不一致之处?我想了解更多,因为我什么都不知道。
Daniel Kamil Kozar 2013年

12
我只是在寻找这个。我不理解对此答案的批评。我喜欢看到一个以上的解决方案。而且,我是一个喜欢awk命令进行bash的人(如果没有别的,因为awk在其他shell中工作)。我更喜欢这种解决方案。但这是我个人的看法。
2014年

4
前导零:echo $(((END-START))| awk'{printf“%02d:%02d \ n”,int($ 1/60),int($ 1%60)}'
Jon Strayer

17

另一种选择是datediffdateutilshttp://www.fresse.org/dateutils/#datediff)使用:

$ 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

您也可以使用gawkmawk1.3.4也有strftime和,mktime但较旧的版本mawknawk没有。

$ 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

请删除我的评论...对不起
Bill Gale

dateutils通过apt 安装后,无需使用datediff命令dateutils.ddiff
Suzana

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:33:56.104
Umesh Rajbhandari 2014年

如果毫秒字段以零开头,则毫秒处理行为不正常。例如ms =“ 033”将给出尾随数字“ 027”,因为ms字段被解释为八进制。只要将“ shopt -s extglob”显示在“脚本。一个人可能还应该从h,m和s中去除前导零...
Eric Towers

3
echo $(((60*60*$((10#$h)))+(60*$((10#$m)))+$((10#$s))))工作对我来说,因为我得到value too great for base (error token is "08")
尼克拉斯

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

sed:公式替换a 以转换为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
瑞安·汤普森

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之间的差是1h 20m:

$ ./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日期(可信赖的Ubuntu 14.04 LTS)推广@nisetama的解决方案:

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

我意识到这是一篇较旧的文章,但是今天我在处理一个脚本时遇到了这个问题,该脚本将从日志文件中获取日期和时间并计算增量。下面的脚本肯定是矫kill过正,我强烈建议您检查一下自己的逻辑和数学。

#!/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.

我对脚本进行了一些修改以使其独立(即,只需设置变量值),但也许也能想到一般的想法。您可能需要对负值进行一些其他错误检查。


哎呀,很多工作!请看一下我的答案: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

未经测试,可能是越野车。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.