Q: I need to determine days between arbitrary dates. I’ve seen epoch seconds as a possible way but this is limited 1970 through 2038 and converting between MDY forms and epoch seconds is fairly tricky.
A: If all you need are the number of days, the simple way is to use the Julian calendar. Note that Julian term is often confused with day of the year (1-365) but in astronomy, the Julian calendar starts Jan 1, 4713 BC. The definition of the calendar includes fractional values to indicate time of day, but for your requirement, just the integer value (days) is sufficient.
Here’s a calculator from the US Naval Observatory with a background on how to convert between Gregorian calendars and Julian calendars.
But for your requirement, there is a math procedure to convert in either direction. Here is a reference to the actual math:
http://pmyers.pcug.org.au/General/JulianDates.htm#G2J
But the two functions listed below will accomplish the math for you. They both assume the US calendar date format: MM DD YYYY. Jdate accepts a 3 character month name (Jan-Dec, upper or lower or mixed case) and Jmdy has an option (-m) to display the month name rather than the number.
Jdate is useful in decoding dates (like syslog.log) which are typically in this format:
Nov 30 08:59:09
So to determine the days between two dates:
J1=$(Jdate Nov 30 2011)
J2=$(Jdate Dec 26 2010)
DAYS=$(($J1 – $J2))
or
DAYS=$(($(Jdate Nov 30 2011) – $(Jdate Dec 26 2010)))
(ans: 339)
Here are the two routines. You can paste them into your scripts or use them from a function library by exporting FPPATH=/yourFunctionDirectory
###########
# Jdate #
###########
function Jdate
{
# Usage: Jdate <month_name> <day> <yearYYYY>
# where month is the 3-char month name or 1-12 month number,
# day and year are integers, year is 4 digits.
# Calculate Julian day from MONTH_NAME DAY YEARYYYY
# It is the number of days since 4713 BC
# The Julian date is the ideal way to compute day differences given calendar dates
# The exact Julian day technically starts at 0.5 Universal Time (noon)
# but this calculation is all integers and computes from 0.0 UT.
set -u
TRACEME=${TRACEME:-false} # TRACEME non-null = trace on
[ $TRACEME != false ] && set -x && PS4='[$LINENO]: ‘
MONRAW=$1
DAY=$2
YEAR=$3
# Convert month to number
# To allow for UPPER or MiXeD case, store in lowercase
# ZerO is a placeholder for the zero-th array element so
# that jan is element 1 in the array.
if ” | wc -c) -ne 0 ]]
then
typeset -l MONTHNAME=$1 # convert month name to lowercase
set -A MON ZerO jan feb mar apr may jun jul aug sep oct nov dec
MONTH=1
while
do
&& break
MONTH=$(($MONTH+1))
done
else
MONTH=$1
fi
# If we get here with MONTH=13, then the month name was not found
# or the month number was not 1-12
if
then
echo “Month: “$MONRAW” not valid”
exit 1
fi
# perform conversion
######################################################
if ; then
MONTH=$(($MONTH – 3))
else
MONTH=$(($MONTH + 9))
YEAR=$(($YEAR – 1))
fi
CENTURY=$(($YEAR / 100))
CENT2=$(($YEAR % 100))
JULIAN=$(((146097 * $CENTURY) / 4
+ (1461 * $CENT2) / 4
+ (153 * $MONTH + 2) / 5
+ $DAY + 1721119))
echo $JULIAN
return
}
##########
# Jmdy #
##########
function Jmdy
{
# Usage: Jmdy [-m] <Julian day number>
# where -m will return 3-char Month Name, otherwise month=1-12
# JulianDayNumber to be converted to Month Day Year
# Calculate MONTH_NAME DAY YEARYYYY from JulianDayNumber
# JulianDayNumber is the number of days since 4713 BC
# This is the ideal way to compute date differences given calendar dates
# The exact Julian day technically starts at 0.5 Universal Time (noon)
# but this calculation is all integers and computes from 0.0 UT.
set -u
TRACEME=${TRACEME:-false} # TRACEME non-null = trace on
[ $TRACEME != false ] && set -x && PS4='[$LINENO]: ‘
set -A MONTH3 ZerO Jan Feb Mar Apr May Jun Jul Aug Sep Oce Nov Dec
MONTHNAME=false
while getopts “:m” OPTCHR
do
case $OPTCHR in
m) MONTHNAME=true
;;
*) eval “ERROPT=$$(($OPTIND-1))”
echo “function Jmdy invalid option: $ERROPT”
return 1
;;
esac
done
shift $(($OPTIND -1))
# Do all the calculations – all integer math
JULIANDATE=$1
JULIANDATE=$((JULIANDATE – 1721119))
YEAR=$(((4 * JULIANDATE – 1) / 146097))
JULIANDATE=$((4 * JULIANDATE – 1 – 146097 * YEAR))
DAY=$((JULIANDATE / 4))
JULIANDATE=$(((4 * DAY + 3) / 1461))
DAY=$((4 * DAY + 3 – 1461 * JULIANDATE))
DAY=$(((DAY + 4) / 4))
MONTH=$(((5 * DAY – 3) / 153))
DAY=$((5 * DAY – 3 – 153 * MONTH))
DAY=$(((DAY + 5) / 5))
YEAR=$((100 * YEAR + JULIANDATE))
if
then
MONTH=$((MONTH + 3))
else
MONTH=$((MONTH – 9))
YEAR=$((YEAR + 1))
fi
&& MONTH=${MONTH3[$MONTH]}
echo “$MONTH $DAY, $YEAR”
return
}
– See more at: http://serviceitdirect.com/blog/using-julian-days-calendar-calculations#sthash.Tv9S2ucB.dpuf
Tags: HP-UX