Noi in realtà non è (ancora) un distacco che affronta il problema generale del numero di giorni tra due date. Allora ho appena finito di quello che dovrebbe essere l'ultima data di calcolo script che io abbia mai scritto. La matematica mi ha dato va bene e sono certo che non ho ancora questo diritto. Ma qui è in ogni caso. Alcuni esempi di ciò che può fare ...
> Datecalc-a 1960 12 31 - 1922 2 2
14212
> Datecalc-a 1960 12 31 + 7
1961 1 7
> Datecalc-D 1960 12 31
Sabato
Ho appena rivisto questo script. Ho aggiunto un opzione-l per calcolare l'ultimo giorno del mese. Ho aggiunto una funzione per fare questo e modificato la funzione date2jd di utilizzare questa nuova funzione. Ho migliorato il messaggio di errore e ha aggiunto un opzione per l'aiuto speriamo datecalc rendere auto-documentare.
Come in precedenza, se si trova qualsiasi bug fatemelo sapere. Ans se trovare qualsiasi data manipolazione necessità che non può fare fatemelo sapere che, come bene. Ho ancora qualche speranza che questo script in grado di risolvere tutti i problemi data la manipolazione.
Ecco la nuova versione ...
Codice:
#! /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