Home > Enterprise >  Time difference in shell (hour)
Time difference in shell (hour)

Time:09-06

I'm trying to calculate time difference stored inside of two variables inside of a shell script, I'm observing the following pattern: hhmm -> 0950

so:

time1=1333
time2=0950

Now I need to calculate the difference in time between time1 and time2, as for now I have tried:

deltaTime=$(($time1-$time2))

but I'm facing the following error message

1333-0950: value too great for base (error token is "0950")

I'm expecting as a result: $deltaTime=0343

Unfortunately, I am strictly bound to use this time pattern. I have already researched for a solution online, some of them propose to use date -d... but I couldn't get it to work :(

CodePudding user response:

Your approach has two issues.

First issue: bash recognizes numbers with leading zeroes as octal. You can force base10 by adding 10# prefix.

Second issue: it is incorrect to consider strings in hhmm format as numbers and substract them. e.g. 1333-950=383 but difference between 09:50 and 13:33 is 3 hours and 43 minutes. You should convert string values to common units, e.g. to minutes, substract them and convert back to hhmm format.

time1=1333
time2=0950

str2min()
{
    printf "%u" $((10#${1%??} * 60   10#${1#??}))
}

min2str()
{
    printf "uu" $(($1 / 60)) $(($1 % 60))
}

time1m=$(str2min $time1)
time2m=$(str2min $time2)

timediff=$(($time1m - $time2m))

deltaTime=$(min2str $timediff)

CodePudding user response:

Do you have the possibility to drop the leading zero?

As you can see from my prompt:

Prompt> echo $((1333-0950))
-bash: 1333-0950: value too great for base (error token is "0950")
Prompt> echo $((1333-950))
383

Other proposal:

date ' %s'

Let me give you some examples:

date ' %s'
1662357975
... (after some time)
date ' %s'
1662458180

=>

echo $((1662458180-1662357975))
100205 (amount of seconds)

=>

echo $(((1662458180-1662357975)/3600))
27 (amount of hours)

CodePudding user response:

You could use this implementation maybe?

#!/usr/bin/env bash

diff_hhmm() {
  local -r from=$1
  local -i from_hh=10#${from:0:2}  # skip 0 chars, read 2 chars (`${from:0:2}`) using base 10 (`10#`)
  local -ri from_mm=10#${from:2:2} # skip 2 chars, read 2 chars (`${from:0:2}`) using base 10 (`10#`)

  local -r upto=$2
  local -ri upto_hh=10#${upto:0:2}
  local -ri upto_mm=10#${upto:2:2}

  local -i diff_hh
  local -i diff_mm

  # Compute difference in minutes
  (( diff_mm = from_mm - upto_mm ))

  # If it's negative, we've "breached" into the previous hour, so adjust
  # the `diff_mm` value to be modulo 60 and compensate the `from_hh` var
  # to reflect that we've already subtracted some of the minutes there.
  if (( diff_mm < 0 )); then
    (( diff_mm  = 60 ))
    (( from_hh -= 1 ))
  fi

  # Compute difference in hours
  (( diff_hh = from_hh - upto_hh ))

  # Ensure the result is modulo 24, the number of hours in a day.
  if (( diff_hh < 0 )); then
    (( diff_hh  = 24 ))
  fi

  # Print the values with 0-padding if necessary.
  printf 'dd\n' "$diff_hh" "$diff_mm"
}
$ diff_hhmm 1333 0950
0343
$ diff_hhmm 0733 0950
2143
$ diff_hhmm 0733 0930
2203
  • Related