我使用日期+“%T”打印开始和结束时间,结果如下:

10:33:56
10:36:10

我如何计算并打印这两者之间的差值呢?

我想要的是:

2m 14s

当前回答

下面是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"

其他回答

我知道这是一篇较老的文章,但我今天在编写一个脚本时偶然发现了它,该脚本将从日志文件中获取日期和时间并计算delta。下面的脚本当然是多余的,我强烈建议检查我的逻辑和数学。

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

我修改了一点脚本,使其独立(即。只是设置变量值),但也许总体思想也是如此。您可能需要对负值进行额外的错误检查。

另一种选择是使用dateutils (http://www.fresse.org/dateutils/#datediff):)中的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

你也可以用gawk。Mawk 1.3.4也有strftime和mktime,但旧版本的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 -ud@$(($(date -ud'1970-01-01 10:36:10' +%s)-$(date -ud'1970-01-01 10:33:56' +%s))) +%T
00:02:14

我想提出另一种避免召回日期命令的方法。如果你已经收集了%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"

我需要一个时差脚本用于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])
% start=$(date +%s)
% echo "Diff: $(date -d @$(($(date +%s)-$start)) +"%M minutes %S seconds")"
Diff: 00 minutes 11 seconds