17

I have two time strings; eg. "09:11" and "17:22" on the same day (format is hh:mm). How do I calculate the time difference in minutes between these two?

Can the standard date library do this?

Example:

#!/bin/bash

MPHR=60    # Minutes per hour.

CURRENT=$(date -u -d '2007-09-01 17:30:24' '+%F %T.%N %Z')
TARGET=$(date -u -d'2007-12-25 12:30:00' '+%F %T.%N %Z')

MINUTES=$(( $(diff) / $MPHR ))

Is there a simpler way of doing this given the hour and minute in hh:mm

gorn
  • 8,097
  • 5
  • 37
  • 44

6 Answers6

21

A pure solution :

old=09:11
new=17:22

# feeding variables by using read and splitting with IFS
IFS=: read old_hour old_min <<< "$old"
IFS=: read hour min <<< "$new"

# convert hours to minutes
# the 10# is there to avoid errors with leading zeros
# by telling bash that we use base 10
total_old_minutes=$((10#$old_hour*60 + 10#$old_min))
total_minutes=$((10#$hour*60 + 10#$min))

echo "the difference is $((total_minutes - total_old_minutes)) minutes"

Another solution using date (we work with hour/minutes, so the date is not important)

old=09:11
new=17:22

IFS=: read old_hour old_min <<< "$old"
IFS=: read hour min <<< "$new"

# convert the date "1970-01-01 hour:min:00" in seconds from Unix EPOCH time
sec_old=$(date -d "1970-01-01 $old_hour:$old_min:00" +%s)
sec_new=$(date -d "1970-01-01 $hour:$min:00" +%s)

echo "the difference is $(( (sec_new - sec_old) / 60)) minutes"

See http://en.wikipedia.org/wiki/Unix_time

Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
  • In the date solution I get: usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ... [-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format] – gorn Jan 14 '13 at 08:56
  • The first one works :) Thanks! But I think date is used incorrectly since I get usage errors – gorn Jan 14 '13 at 09:31
  • The `date` solution works well for me. There was some missing parentheses in the last arithmetic operation (corrected). date (GNU coreutils) 8.20 – Gilles Quénot Jan 14 '13 at 20:08
  • Some might find `date -ud '0000-01-01 10 seconds - 0 seconds' '+%FT%T';` also interesting, though it may returns incorrect time if used as the difference between the current since time shifts. – Artfaith Jun 12 '22 at 03:49
19

I would convert the dates to UNIX timestamps; you can subtract to get the difference in seconds, then divide by 60:

#!/bin/bash

MPHR=60    # Minutes per hour.

CURRENT=$(date +%s -d '2007-09-01 17:30:24')
TARGET=$(date +%s -d'2007-12-25 12:30:00')

MINUTES=$(( ($TARGET - $CURRENT) / $MPHR ))
chepner
  • 497,756
  • 71
  • 530
  • 681
9

Here is how I did it:

START=$(date +%s);
sleep 1; # Your stuff
END=$(date +%s);
echo $((END-START)) | awk '{printf "%d:%02d:%02d", $1/3600, ($1/60)%60, $1%60}'

Really simple, take the number of seconds at the start, then take the number of seconds at the end, and print the difference in minutes:seconds.

Community
  • 1
  • 1
Dorian
  • 22,759
  • 8
  • 120
  • 116
7

I was looking for a solution with seconds. Found here: How to calculate time difference in bash script?

#!/bin/bash
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"

Here I have added seconds to Gilles' solution:

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;
}
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
4
MPHR=60
CURRENT=09:11
TARGET=17:22
echo $(( ( 10#${TARGET:0:2} - 10#${CURRENT:0:2} ) * MPHR + 10#${TARGET:4} - 10#${CURRENT:4} ))
Neil
  • 54,642
  • 8
  • 60
  • 72
3
STARTTIME=$(date +%s)

YOUR CODES :

ENDTIME=$(date +%s)
secs=$(($ENDTIME - $STARTTIME))
printf 'Elapsed Time %dh:%dm:%ds\n' $(($secs/3600)) $(($secs%3600/60)) $(($secs%60)) 
vjdhama
  • 4,878
  • 5
  • 33
  • 47
Mark Narag
  • 31
  • 1
  • 1
    I think you should edit your answer just in order it to be easier readable and understandable. Also include additional comments to clarify your answer. – ZygD Mar 28 '15 at 21:23