268 lines
6.3 KiB
Bash
Executable file
268 lines
6.3 KiB
Bash
Executable file
#! /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
|