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 gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

date manipulation

Status
Not open for further replies.

csunix

Programmer
Mar 23, 2004
129
GB
I am calculating "yesterdays date" but am losing the leading zero aon the day and month.
 
Take a look here: faq822-4802

Hope This Help, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884
 
The following function library might be of some help to you. I got the outline logic for this from somewhere in the internet and added my improvements to these functions.

*********** START LIBRARY SCRIPT **********
#!/bin/ksh

#=========================================================================
dateAdd() # Adds number of days to a given date
#=========================================================================
# ARG_1 -> The date to add days DDMMYYYY format
# ARG_2 -> The number of days to add
# ARG_3 -> The date is returned in which format?
# 1 -> dd/mm/yyyy
# 2 -> mm/dd/yyyy
# 3 -> dd/mm/yy
# 4 -> mm/dd/yy
{

# Check that the input is valid.
# There should be exactly 3 arguments
if [ $# -ne 3 ]; then
return 1
fi

# The argument should be an integer.
n=`expr $2 + 0 2> /dev/null`
if [ $? -ne 0 ]; then
qnbad=0
elif [ $n -lt 0 ]; then
qnbad=0
else
qnbad=1
fi

if [ $qnbad -eq 0 ]; then
return 1
fi

# The "local" defnitions help to trickily
# return the values to the caller
local day=''
local month=''
local year=''

# Set the month day and year.
day=`echo $1 | cut -c1-2`
month=`echo $1 | cut -c3-4`
year=`echo $1 | cut -c5-8`

# Add 0 to month. This is a
# trick to make month an unpadded integer.
month=`expr $month + 0`

# Add n to the current day.
day=`expr $day + $n`

# Add months and subtract days until
# the future date is reached.
while : # Indefinite TRUE loop
do
# Determine the number of days in the
# current month.
case $month in
1|3|5|7|8|10|12) curMonthDay=31;;
4|6|9|11) curMonthDay=30;;
2)
if [ `expr $year % 4` -eq 0 ]; then
if [ `expr $year % 400` -eq 0 ]; then
curMonthDay=29
elif [ `expr $year % 100` -eq 0 ]; then
curMonthDay=28
else
curMonthDay=29
fi
else
curMonthDay=28
fi
;;
esac

# If the day is greater than the number
# of days in the current month then
# month is incremented; otherwise we are done.
if [ $day -gt $curMonthDay ]; then
day=`expr $day - $curMonthDay`
month=`expr $month + 1`

# If the month is 13 then it is jan of
# next year.
if [ $month -eq 13 ]; then
month=1
year=`expr $year + 1`
fi
else
break
fi
done

# Pad the integers before sending
[ $day -lt 10 ] && day="0$day"
[ $month -lt 10 ] && month="0$month"

# Print the month day and year according to the format
case "$3" in
1) echo $day'/'$month'/'$year;;
2) echo $month'/'$day'/'$year;;
3) echo $day'/'$month'/'`echo $year | cut -c3-4`;;
4) echo $month'/'$day'/'`echo $year | cut -c3-4`;;
esac

exit 0
}

#=========================================================================
dateSub() # Subtracts number of days to a given date
#=========================================================================
# ARG_1 -> The date to subtract days DDMMYYYY format
# ARG_2 -> The number of days to subtract
# ARG_3 -> The date is returned in which format?
# 1 -> dd/mm/yyyy
# 2 -> mm/dd/yyyy
# 3 -> dd/mm/yy
# 4 -> mm/dd/yy
{
# Check that the input is valid.
# There should be exactly 3 arguments.
if [ $# -ne 3 ]; then
return 1
fi

# The argument should be an integer.
n=`expr $2 + 0 2> /dev/null`
if [ $? -ne 0 ]; then
qnbad=0
elif [ $n -lt 0 ]; then
qnbad=0
else
qnbad=1
fi

if [ $qnbad -eq 0 ]; then
return 1
fi

# The "local" defnitions help to trickily
# return the values to the caller
local day=''
local month=''
local year=''

# Set the month day and year.
day=`echo $1 | cut -c1-2`
month=`echo $1 | cut -c3-4`
year=`echo $1 | cut -c5-8`

# Add 0 to month. This is a
# trick to make month an unpadded integer.
month=`expr $month + 0`

# Subtrace n from the current day.
day=`expr $day - $n`

# While the day is less than or equal to
# 0, deincrement the month.
while [ $day -le 0 ]
do
month=`expr $month - 1`

# If month is 0 then it is Dec of last year.
if [ $month -eq 0 ]; then
year=`expr $year - 1`
month=12
fi

# Add the number of days appropriate to the
# month.
case $month in
1|3|5|7|8|10|12) day=`expr $day + 31`;;
4|6|9|11) day=`expr $day + 30`;;
2)
if [ `expr $year % 4` -eq 0 ]; then
if [ `expr $year % 400` -eq 0 ]; then
day=`expr $day + 29`
elif [ `expr $year % 100` -eq 0 ]; then
day=`expr $day + 28`
else
day=`expr $day + 29`
fi
else
day=`expr $day + 28`
fi
;;
esac
done

# Pad the integers before sending
[ $day -lt 10 ] && day="0$day"
[ $month -lt 10 ] && month="0$month"

# Print the month day and year according to the format
case "$3" in
1) echo $day'/'$month'/'$year;;
2) echo $month'/'$day'/'$year;;
3) echo $day'/'$month'/'`echo $year | cut -c3-4`;;
4) echo $month'/'$day'/'`echo $year | cut -c3-4`;;
esac
exit 0

}
*********** END LIBRARY SCRIPT **********
 
A Perderabo's script take on a other forum
It is really good



#! /usr/bin/ksh

# datecalc -- Perderabo's date calculator
#

USAGE="datecalc -a year month day - year month day
datecalc -a year month day [-|+] n
datecalc -d year month day
datecalc -D year month day
datecalc -j year month day
datecalc -j n
datecalc -l year month
use \"datecalc -help\" use for more documentation"

DOCUMENTATION=" datecalc Version 1.1

datecalc does many manipulations with dates.
datecalc -a is for date arithmetic
datecalc -d or -D converts a date to the day of week
datecalc -j converts to date to or from julian day
datecalc -l outputs the last day of a month

All dates must be between the years 1860 and 3999.

datecalc -a followed by 7 parameters will calculate the
number of days between two dates. Parameters 2-4 and 6-8
must be dates in ymd form, and parameter 5 must be a minus
sign. The output is an integer. Example:

> datecalc -a 1960 12 31 - 1922 2 2
14212


datecalc -a followed by 5 parameters will calculate the
a new date offset from a given date, Parameters 2-4 must
be a date in ymd form, paramter 5 must be + or -, and
paramter 6 must be an integer. Output is a new date.
Example:

> datecalc -a 1960 12 31 + 7
1961 1 7


datecalc -d followed by 3 parameters will convert a date
to a day-of-week. Parameters 2-4 must be a date in ymd
form. Example:

> datecalc -d 1960 12 31
6


datecalc -D is like -d except it displays the name of
the day. Example:

> datecalc -D 1960 12 31
Saturday


datecalc -j followed by 3 parameters will convert a date
to Modified Julian Day number. Example:
> datecalc -j 1960 12 31
37299


datecalc -j followed by a single parameter will convert
a Modified Julian Day number to a date. Example:
> datecalc -j 37299
1960 12 31


datecalc -l followed by year and month will output the last
day of that month. Note that by checking the last day of
February you can test for leap year. Example:
> datecalc -l 2002 2
28"


lastday() {
integer year month leap
# ja fe ma ap ma jn jl ag se oc no de
set -A mlength xx 31 28 31 30 31 30 31 31 30 31 30 31

year=$1
if ((year<1860 || year> 3999)) ; then
print -u2 year out of range
return 1
fi
month=$2
if ((month<1 || month> 12)) ; then
print -u2 month out of range
return 1
fi

if ((month != 2)) ; then
print ${mlength[month]}
return 0
fi

leap=0
if ((!(year%100))); then
((!(year%400))) && leap=1
else
((!(year%4))) && leap=1
fi

feblength=28
((leap)) && feblength=29
print $feblength
return 0
}


date2jd() {
integer ijd day month year mnjd jd lday

year=$1
month=$2
day=$3
lday=$(lastday $year $month) || exit $?

if ((day<1 || day> lday)) ; then
print -u2 day out of range
return 1
fi

((standard_jd = day - 32075
+ 1461 * (year + 4800 - (14 - month)/12)/4
+ 367 * (month - 2 + (14 - month)/12*12)/12
- 3 * ((year + 4900 - (14 - month)/12)/100)/4))
((jd = standard_jd-2400001))


print $jd
return 0
}


jd2dow()
{
integer jd dow numeric_mode
set +A days Sunday Monday Tuesday Wednesday Thursday Friday Saturday

numeric_mode=0
if [[ $1 = -n ]] ; then
numeric_mode=1
shift
fi


jd=$1
if ((jd<1 || jd>782028)) ; then
print -u2 julian day out of range
return 1
fi

((dow=(jd+3)%7))

if ((numeric_mode)) ; then
print $dow
else
print ${days[dow]}
fi
return
}

jd2date()
{
integer standard_jd temp1 temp2 jd year month day

jd=$1
if ((jd<1 || jd>782028)) ; then
print julian day out of range
return 1
fi
((standard_jd=jd+2400001))
((temp1 = standard_jd + 68569))
((temp2 = 4*temp1/146097))
((temp1 = temp1 - (146097 * temp2 + 3) / 4))
((year = 4000 * (temp1 + 1) / 1461001))
((temp1 = temp1 - 1461 * year/4 + 31))
((month = 80 * temp1 / 2447))
((day = temp1 - 2447 * month / 80))
((temp1 = month / 11))
((month = month + 2 - 12 * temp1))
((year = 100 * (temp2 - 49) + year + temp1))
print $year $month $day
return 0
}


#
# Parse parameters and get to work.
case $1 in
-a) if (($# == 8)) ; then
if [[ $5 != - ]] ; then
print -u2 - "$USAGE"
exit 1
fi
jd1=$(date2jd $2 $3 $4) || exit $?
jd2=$(date2jd $6 $7 $8) || exit $?
((jd3=jd1-jd2))
print $jd3
exit 0
elif (($# == 6)) ; then
jd1=$(date2jd $2 $3 $4) || exit $?
case $5 in
-|+) eval '(('jd2=${jd1}${5}${6}'))'
jd2date $jd2
exit $?
;;
*)
print -u2 - "$USAGE"
exit 1
;;
esac

fi
;;

-d|-D) if (($# != 4)) ; then
print -u2 - "$USAGE"
exit 1
fi
jd1=$(date2jd $2 $3 $4) || exit $?
numeric=-n
[[ $1 = -D ]] && numeric=""
eval jd2dow $numeric $jd1
exit $?
;;

-j) if (($# == 4)) ; then
date2jd $2 $3 $4
exit $?
elif (($# == 2)) ; then
jd2date $2 $3 $4
exit $?
else
print -u2 - "$USAGE"
exit 1
fi
;;

-l) if (($# == 3)) ; then
lastday $2 $3
exit $?
else
print -u2 - "$USAGE"
exit 1
fi
;;

-help) print - "$USAGE"
print ""
print - "$DOCUMENTATION"
exit 0
;;

*) print -u2 - "$USAGE"
exit 0
;;


esac

#not reached
exit 7
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top