Arithmetic error - calculation taking base as 8
Asked Answered
C

2

2

I am executing the following piece of code. I am not sure why the calculation is happening in octal? How can I make this code better?

#!/bin/bash
gmthour=$(date -u +%H)
localhour=$(date +%H)
echo $gmthour
echo $localhour
tz=$(( gmthour - localhour ))
echo $tz

Error

22
08
MyFile.ksh: line 6: 08: value too great for base (error token is "08")
Chlorpromazine answered 1/7, 2013 at 22:26 Comment(2)
can't duplicate this issue , what version of bash ?Hoarse
Mine is bash-3.00 . I guess whether you get or not get the issue wuilll depend on whether the localhour/gmthour has leading zero or notChlorpromazine
A
1

The leading zero is what causes the number to be interpreted as octal. Quote from man bash:

ARITHMETIC EVALUATION
[...]
Constants with a leading 0 are interpreted as octal numbers. A leading 0x or 0X denotes hexadecimal. Otherwise, numbers take the form [base#]n, where the optional base is a decimal number between 2 and 64 representing the arithmetic base, and n is a number in that base. If base# is omitted, then base 10 is used.

Change the format string of the date commands to %k or %_H to get rid of leading zeroes:

#!/bin/bash
gmthour=$(date -u +%k)
localhour=$(date +%k)
echo $gmthour
echo $localhour
tz=$(( gmthour - localhour ))
echo $tz

Beware that your calculation will break when the day changes. Example:

$ date
Di 2. Jul 00:50:29 CEST 2013
$ gmthour=$(date -u +%k)
$ localhour=$(date +%k)
$ echo $gmthour
22
$ echo $localhour
0
$ echo $((gmthour - localhour))
22

CEST clearly isn't UTC+22.

Try this instead:

#!/bin/bash
gmthour=$(date -u +%k)
localhour=$(date +%k)
echo $gmthour
echo $localhour
if [ $(date +%w) -eq $(date -u +%w) ]; then
  tz=$(( gmthour - localhour ))
else
  tz=$(( 24 - gmthour + localhour ))
fi
echo $tz
Arsonist answered 1/7, 2013 at 22:43 Comment(1)
how would it break . Can you elaborate please?Chlorpromazine
L
1

How about this?

tz=$(( 10#$gmthour - 10#$localhour ))

I am not sure why the calculation is happening in octal

Just because when there's a leading zero, the number is interpreted as being in radix 8. To prevent that, you can impose the shell to interpret number in radix 10 with 10#. But seeing your comment, let me stress that in this case you must explicitly use the dollar sign.

Hope this helps!

Lulalulea answered 1/7, 2013 at 22:27 Comment(3)
Already tried doing that , get MyFile.ksh: line 6: 10#gmthour: value too great for base (error token is "10#gmthour")Chlorpromazine
@Chlorpromazine Watch the dollar signs!Lulalulea
thanks mate. Missed out the dollar sign as specified , while trying the code . Onc ethe sign is back on . The issue is fixed.Chlorpromazine
A
1

The leading zero is what causes the number to be interpreted as octal. Quote from man bash:

ARITHMETIC EVALUATION
[...]
Constants with a leading 0 are interpreted as octal numbers. A leading 0x or 0X denotes hexadecimal. Otherwise, numbers take the form [base#]n, where the optional base is a decimal number between 2 and 64 representing the arithmetic base, and n is a number in that base. If base# is omitted, then base 10 is used.

Change the format string of the date commands to %k or %_H to get rid of leading zeroes:

#!/bin/bash
gmthour=$(date -u +%k)
localhour=$(date +%k)
echo $gmthour
echo $localhour
tz=$(( gmthour - localhour ))
echo $tz

Beware that your calculation will break when the day changes. Example:

$ date
Di 2. Jul 00:50:29 CEST 2013
$ gmthour=$(date -u +%k)
$ localhour=$(date +%k)
$ echo $gmthour
22
$ echo $localhour
0
$ echo $((gmthour - localhour))
22

CEST clearly isn't UTC+22.

Try this instead:

#!/bin/bash
gmthour=$(date -u +%k)
localhour=$(date +%k)
echo $gmthour
echo $localhour
if [ $(date +%w) -eq $(date -u +%w) ]; then
  tz=$(( gmthour - localhour ))
else
  tz=$(( 24 - gmthour + localhour ))
fi
echo $tz
Arsonist answered 1/7, 2013 at 22:43 Comment(1)
how would it break . Can you elaborate please?Chlorpromazine

© 2022 - 2024 — McMap. All rights reserved.