Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to use cal command to find second to last day of month 1

Status
Not open for further replies.

spconway

MIS
May 25, 2000
16
US
hello script gurus. I am in need of your guidance with this script. I am having problems when script runs in January and September. Any help would be greatly appreciated!
*********************************
#!/usr/bin/ksh93
#DATE:11/29/04
#NAME: /usr/scripts/setarperdays.ksh
#
# Script determines next, current, last month's and two month's ago last day of
# month. It then subtracts one day.
# Puts day variables into sascarperdays.p file

# LOGIC: Take the current month's number of days and subtract one
# to equal arperdays[1] = day number variable
#
# arperdays[1] = (days in next month) - 1
# arperdays[2] = (days in current month) -1
# arperdays[3] = (days in last month) -1
# arperdays[4] = (days in two months ago) -1

################################################################################
cd /usr/scripts
#
N=1
# Last day of next month
typeset -Z4 year=$(date +%Y)
typeset -Z2 month=$(( $(date +%m) + 1 ))
if [ $month -eq 13 ] ;
then
(( year += 1 ))
month=1
fi
next_month=${year}${month}
A=`echo $next_month|cut -c 1-4` # 4 digit year
B=`echo $next_month|cut -c 5-6` # 2 digit month
C=`cal "$B" "$A"`
D=${C##*[!0-9]}
V1=`expr $D - $N`

# thread822-839081 from tek-tips.com
# Last Day of This Month
val=$(cal)
val=${val##*[!0-9]}
V2=`expr $val - $N`

# thread80-768784 from tek-tips.com
# Last day of last month
typeset -Z4 year=$(date +%Y)
typeset -Z2 month=$(( $(date +%m) -1 ))
if [ $month -eq 0 ] ;
then
(( year -= 1 ))
month=12
fi
last_month=${year}${month}
E=`echo $last_month|cut -c 1-4` # 4 digit year
F=`echo $last_month|cut -c 5-6` # 2 digit month
G=`cal "$F" "$E"`
H=${G##*[!0-9] }
V3=`expr $H - $N`

# Last day of two months ago
typeset -Z4 year=$(date +%Y)
typeset -Z2 month=$(( $(date +%m) -2 ))
if [ $month -le 0 ] ;
then
(( year -= 1 ))
month=12
fi
two_month_ago=${year}${month}
I=`echo $two_month_ago|cut -c 1-4` # 4 digit year
J=`echo $two_month_ago|cut -c 5-6` # 2 digit month
K=`cal "$J" "$I"`
H=${K##*[!0-9]}
V4=`expr $H - $N`

echo "for each sasc where sasc.cono = 1 exclusive-lock: \n
assign \n
arperdays[1] = $V1 /* days in next month -1 */ \n
arperdays[2] = $V2 /* days in current month -1 */ \n
arperdays[3] = $V3 /* days in last month -1 */ \n
arperdays[4] = $V4 . /* days in last 2 months ago -1 */ \n " > sascarperdays.p
 
Use this awk program to get the number of days in a month. You can pass it a month-number greater than 12 or less than 1.
In other words, "2005 0" is equivalent to "2004 12" and "2003 14" is equivalent to "2004 2".
[tt]
echo "2003 14" |awk -f days_in_month.awk
[/tt]
produces
[tt]
29
[/tt]
Code:
BEGIN {
  split("31 28 31 30 31 30 31 31 30 31 30 31",
        days_in_month)
}

{ year = $1
  month = $2
  if (month > 12)
  { year++
    month -= 12
  }
  if (month < 1)
  { year--
    month += 12
  }
#   printf "%d %d\n", year, month
  print days_in_month[month] + \
    (2==month && leap_year(year))
}

function leap_year(y)
{ return !(y%4 || y%400 && !(y%100) )
}
 
In the last day of two months ago calculation replace this:
month=12
By this:
(( month += 12 ))

Hope This Helps, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884 or FAQ222-2244
 
Hi gurus: thanks again for the help with this script! Script has been running well for the past few months but on July 25 when it ran last I received the following error:

/rd/bin/setarperdays.ksh: line 28: .
08 + 1 : arithmetic syntax error.

Any ideas why?
 
Here is the whole script that I am running now:

#!/usr/bin/ksh93
#
# DATE:11/29/04
# NAME: /rd/bin/setarperdays.ksh
#
#*******************************************************************************
# Script determines next, current, last month's and two month's ago last day of
# month. It then subtracts one day.
# Puts day variables into sascarperdays.p file
# Compiles sascarperdays.p file in /rd/qd
# Sends an email notification that this script has run and internals
# of sascarperdays.p have been changed. Internal lines sent in body
# of message.
#
# LOGIC: Take the current month's number of days and subtract one
# to equal arperdays[1] = day number variable
#
# arperdays[1] = (days in next month) - 1
# arperdays[2] = (days in current month) -1
# arperdays[3] = (days in last month) -1
# arperdays[4] = (days in two months ago) -1
############################################################################
cd /rd/qd
#
N=1
# Last day of next month
typeset -Z4 year=$(date +%Y)
typeset -Z2 month=$(( $(date +%m) + 1 ))
if [ $month -eq 13 ] ;
then
(( year += 1 ))
month=1
fi
next_month=${year}${month}
A=`echo $next_month|cut -c 1-4` # 4 digit year
B=`echo $next_month|cut -c 5-6` # 2 digit month
C=`cal "$B" "$A"`
D=${C##*[!0-9]}
V1=`expr $D - $N`

# thread822-839081 from tek-tips.com
# Last Day of This Month
val=$(cal)
val=${val##*[!0-9]}
V2=`expr $val - $N`

# thread80-768784 from tek-tips.com
# Last day of last month
typeset -Z4 year=$(date +%Y)
typeset -Z2 month=$(( $(date +%m) -1 ))
if [ $month -eq 0 ] ;
then
(( year -= 1 ))
month=12
fi
last_month=${year}${month}
E=`echo $last_month|cut -c 1-4` # 4 digit year
F=`echo $last_month|cut -c 5-6` # 2 digit month
G=`cal "$F" "$E"`
H=${G##*[!0-9] }
V3=`expr $H - $N`

# Last day of two months ago
typeset -Z4 year=$(date +%Y)
typeset -Z2 month=$(( $(date +%m) -2 ))
if [ $month -le 0 ] ;
then
(( year -= 1 ))
(( month += 12))
fi
two_month_ago=${year}${month}
I=`echo $two_month_ago|cut -c 1-4` # 4 digit year
J=`echo $two_month_ago|cut -c 5-6` # 2 digit month
K=`cal "$J" "$I"`
H=${K##*[!0-9]}
V4=`expr $H - $N`

echo "for each sasc where sasc.cono = 1 exclusive-lock: \n
assign \n
arperdays[1] = $V1 /* days in next month -1 */ \n
arperdays[2] = $V2 /* days in current month -1 */ \n
arperdays[3] = $V3 /* days in last month -1 */ \n
arperdays[4] = $V4 . /* days in last 2 months ago -1 */ \n " > sascarperdays.p
wait
cd /rd/qd
. /rd/bin/nxt.env

(/rd/taxware3.4/_taxware -b -pf /rd/opsys/batch.pf -p /rd/qd/comp-sascarperdays.p)
wait
LOG=/rd/qd/comp-sascarperdays.log
echo "sascarperdays.p set and compiled at `date`" > $LOG
echo "" >> $LOG
echo "" >> $LOG
ls -l /rd/qd/sascarperdays* >> $LOG
echo "" >> $LOG
echo "" >> $LOG
cat /rd/qd/sascarperdays.p >> $LOG
echo "" >> $LOG
MAIL_TO="name@yourcompany.com"
mail -s 'SASCARPERDAYS compiled on RSDEV002 for MONTH END Process' $MAIL_TO < $LOG
mail -s 'SASCARPERDAYS Error Log on RSDEV002-Good if body is blank' $MAIL_TO < /rd/tmp/setarperdays.ksh.err
 
Thanks: I am working on a server without PHP. Would Perl work better for this?
 
The reason you get the arithmetic error is because you have an invalid number:

A number starting with a zero is in a lot of unix programs considered an octal number, hence you cannot have a digit greater than 7 in the number. You would get this error for month august and september. Just strip of the leading zero in this case:

Code:
# typeset -Z2 month=$(( $(date +%m) + 1 ))
ksh: 09 + 1 : 0403-009 The specified number is not valid for this command.
# typeset -Z2 month=$(( $(date +%m|sed 's/^0*//') + 1 ))
# echo $month                                           
10

HTH,

p5wizard
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top