Need help with date arithmetic please

Hello fellow forum members,

I wrote below piece of code to calculate the date after a given date -

date=$DATE_FINAL
declare -a  max_month=(0 31 28 31 30 31 30 31 31 30 31 30 31)
eval $(echo $date|sed 's!\(....\)\(..\)\(..\)!year=\1;month=\2;day=\3!')
(( year4=year%4 ))
(( year100=year%100 ))
(( year400=year%400 ))
if [ \( $year4 -eq 0 -a \
        $year100 -ne 0 \) -o \
     $year400 -eq 0 ]
then
declare -a  max_month=(0 31 28 31 30 31 30 31 31 30 31 30 31)
fi
day=$((day+1))
if [ $day -gt ${max_month[$month]} ] >| /wload/baot/home/baoted9/logs_bde27_conversion_1/ataa_display.logs 2>&1
then
  day=1
  month=$((month+1))
  if [ $month -gt 12 ]
  then
    year=$((year+1))
    month=1
  fi
fi
if [ $month -eq "08" ] ||  [ $month -eq "09" ]
then
future_date_final=$(echo $year"$month"$day)
else
future_date_final=$(printf "%4.4d%2.2d%2.2d" $year $month $day)
fi
echo "this is your final business date $future_date_final"

It calculates the date correctly however throws an error at the end of the code as below -

line 79: 08: value too great for base (error token is "08")

It just looks too ugly, not sure how to remove it as otherwise code is working fine, tried redirecting it to a log file still appearing.
Also, I am facing issue with below code for a plain cd command with code highlighted in red -

echo "pset  date $Param_date_1"
cd /wload/baot/home/baotasa0/sandboxes_finance/ext_ukba_bde/pset >| /wload/baot/home/baoted9/logs_bde27_conversion_1/at_display.logs 2>&1
sh UKBA_publish.sh UKBA $Param_date_1 3 >| /wload/baot/home/baoted9/logs_bde27_conversion_1/ate_display.logs 2>&1

Error is -

./auto2.sh: line 190: syntax error: unexpected end of file

Any leads will be greatly appreciated.

My opinion is that coding date arithmetic and not using existing tools is foolish and error prone. I cannot tell what system you are on, most systems have perl.

#!/bin/sh
# ago.shl
# usage: ago.shl [number] 
#       for date [number] days ago,
#       ./ago.shl -3 
#   parm $1 == days in past e.g., yesterday = -1,
#              days in future e.g., tomorrow = 1 

ago()
{
   perl -e ' my $delta = $ARGV[0];
             $delta*=86400;          #  seconds in a day
             $delta=time + $delta;   #  epoch seconds today plus ( or minus) delta
              ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
                                                            localtime($delta);
             
             printf("%04d%02d%02d%02d%02d.%02d\n",
                     $year+1900, $mon+1, $mday;
             ' $1
}

# example usage of the function ago

when=$(ago $1)
echo "$when"

exit 0

If you are on Linux I would HIGHLY recommend that you use the date command which is very reliable and actually supports options like yesterday and tomorrow. Skip using the perl above.

The "value too great for base" happens because there is a number with a leading zero, and bash assumes octal, and 8 is too high for an octal number.
It happens with

day=$((day+1))

or later with month .
As always there is an escape from such (mis)feature: a 10# prefix forces a base10=decimal

day=$((10#$day+1))
month=$((10#$month))

Now the leading zero are removed.

---------- Post updated at 11:15 ---------- Previous update was at 10:52 ----------

You certainly want

if [ \( $year4 -eq 0 -a \
        $year100 -ne 0 \) -o \
     $year400 -eq 0 ]
then
declare -a  max_month=(0 31 29 31 30 31 30 31 31)
fi

As Jim said, such calculations are error prone.
perl is safer because it uses the libc routines.

Also try my general purpose date script which is a limited gnu-date-alike written in Perl.

You might like this for the leap year stuff:

function mthdays { TA=312831303130313130313031; printf "%d\n" $(( ${TA:($1-1)*2:2} + ($1!=2?0:!($2%4) && ($2%100) || !($2%400)))); }
echo $(mthdays 2 2016)
29
echo $(mthdays 2 2015)
28

For the function definition, you need to switch off bash 's history : set +H

Hi.

A collection of suggestions:

Date, time arithmetic, math

        1) gnu date

        2) ksh ( version 93, not 88; ksh93 M 93t+ ) printf, e.g:
           printf "%(%Y-%m-%d)T\n" "yesterday"
           Many more examples ( as of 2017.07 ):
           http://blog.fpmurphy.com/2008/10/ksh93-date-manipulation.html

        3) date.pl (limited arithmetic, but "date.pl -d '- 1 day'" works)
           ( http://www.unix.com/tips-tutorials/
           239167-general-purpose-date-script.html )

        4) dconv et al, e.g. ddiff, dconv, strptime (parsing), etc.
           ( dateutils: http://www.fresse.org/dateutils/ )

        5) tm2tm (, OK in 32-bit; fails to compile in 64-bit)
           ( http://www.unix.com/shell-programming-scripting/
           146216-date-difference-between-freebsd-linux.html#post302463136 )

        6) perl custom formatting (with function POSIX::strftime, "perldoc POSIX")

        7) date-cpan.pl, cpan perl date
           ( http://cpansearch.perl.org/src/CWEST/ppt-0.14/src/date/date.jgross )

        8) For small changes, say, "yesterday" in bash, ksh
           TZ=CST+24 date +%Y%m%d
           csh, tcsh
           setenv TZ CST+24 ; date +%Y%m%d

        9) Check for legal date:
           manstat:validata ( http://oldwww.acm.org/perlman/stat/ )

        10) Check for legal date:
            validate (local perl code)

        11) Shell, ksh, date calculations:
            www.unix.com/unix-for-dummies-questions-and-answers/4870-days-elapsed-between-2-dates.html

Best wishes ... cheers, drl

Thanks madeingermany...I tried but the error is still because of line I mentioned in my first post n I am using AIX so most of the commands don't work...I need to do date calculation for an arbitrary date so tz doesn't work for me either :frowning:
~Ekta

Did you replace the day=$((day+1)) by the two lines I gave you?
And do you run your script with bash?
Run it with

bash -xv ./scriptname ...

and you see what it does.

I tried that, but it didn't work and threw error on the same line I mentioned in the first post :frowning: ...will run with -xv option tomorrow n share the logs

Exactly the situation my general purpose date script was designed for - when you need the GNU tools and don't have them.