#!/bin/sh
#
#	Copyright (c) 1986-2005, Hiram Clawson - jday at hiram.ws
#	All rights reserved.
#
#	Redistribution and use in source and binary forms, with or
#	without modification, are permitted provided that the following
#	conditions are met:
#
#		Redistributions of source code must retain the above
#		copyright notice, this list of conditions and the
#		following disclaimer.
#
#		Redistributions in binary form must reproduce the
#		above copyright notice, this list of conditions and
#		the following disclaimer in the documentation and/or
#		other materials provided with the distribution.
#
#		Neither name of The Museum of Hiram nor the names of
#		its contributors may be used to endorse or promote products
#		derived from this software without specific prior
#		written permission. 
#
#	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
#	CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
#	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#	MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
#	IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
#	INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#	(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
#	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
#	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
#	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
#	THE POSSIBILITY OF SUCH DAMAGE. 
#
##############################################################################
#
#	This jday.awk is a quick conversion of the jday.c and caldate.c
#		routines to a shell function that uses awk to do the
#		calculations.  These calculations have not yet been
#		extensively checked.  (2002-11-10)  However in initial
#		experiments they have behaved quite well.
#
##############################################################################
#
#	CalDate computes the day of the week, the day of the year
#	the gregorian (or julian) calendar date and the universal
#	time from the julian decimal date.
#	for astronomical purposes, The Gregorian calendar reform occurred
#	on 15 Oct. 1582.  This is 05 Oct 1582 by the julian calendar.
#
#	Input:	a ut_instant structure pointer, where the j_date element
#		has been set. ( = 0 for 01 Jan -4712 12 HR UT )
#
#	output:  will set all the other elements of the structure.
#		As a convienence, the function will also return the year.
#
#	Reference: Astronomial formulae for calculators, meeus, p 23
#	from fortran program by F. Espenak - April 1982 Page 277,
#	50 Year canon of solar eclipses: 1986-2035
#
#
#
#include "jday.h"	/*	time structures	*/

#	The structure of a date is:

#typedef struct ut_instant {
#	double	j_date; /* julian decimal date, 0 = 01 Jan -4712 12 HR UT */
#	int	year; /* year, valid range [-4,712, +2,147,483,647] */
#	int	month;	/*	[1-12]	*/
#	int	day;	/*	[1-31]	*/
#	int	i_hour;	/*	[0-23]	*/
#	int	i_minute;	/*	[0-59]	*/
#	int	second;	/*	[0-59.9999]	*/
#	double	d_hour;		/* [0.0-23.9999] includes minute and second */
#	double	d_minute;	/*	[0.0-59.9999] includes second	*/
#	int	weekday;	/*	[0-6]	*/
#	int	day_of_year;	/*	[1-366]	*/
#} UTinstant, * UTinstantPtr;

Version() {
echo "jday.awk - version 2.4 - 2005-10-10 10:10:10 UTC - JD 2453653.923727"
echo "\t%Copyright(C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 - jday at hiram.ws"
}

Usage() {
	echo "usage: jday.awk [year [month [day [hour [minute] [second]]]]]"
	echo "\tor: jday.awk -d year-month-day hour:minute:second"
	Version
}

ymdhms=`date -u +"%Y-%m-%d %H:%M:%S"`

DONE=0
COUNT=0

while [ $# -gt 0 ]
do
case $1 in
	-d|--d) if [ $# -ne 3 ]; then
			Usage
		fi
		ymdhms="$2 $3"
		shift
		shift
		DONE=1
			;;
	-h|--h|-help|--help) Usage
		;;
	-v|--v|-version|--version) Version
		;;
	*) COUNT=`expr $COUNT + 1`
		case $COUNT in
			6) ymdhms="$ymdhms$1"
				;;
			5) ymdhms="$ymdhms$1:"
				;;
			4) ymdhms="$ymdhms$1:"
				;;
			3) ymdhms="$ymdhms$1 "
				;;
			2) ymdhms="$ymdhms$1/"
				;;
			1) ymdhms="$1/"
				;;
		esac
		;;
esac
shift
done

if [ $DONE -eq 0 ]; then
	case $COUNT in
		6) DONE=1
			;;
		5) ymdhms=$ymdhms`date -u +"%S`
			;;
		4) ymdhms=$ymdhms`date -u +"%M:%S`
			;;
		3) ymdhms=$ymdhms`date -u +"%H:%M:%S`
			;;
		2) ymdhms=$ymdhms`date -u +"%d %H:%M:%S`
			;;
		1) ymdhms=$ymdhms`date -u +"%m/%d %H:%M:%S`
			;;
	esac
fi

echo "$ymdhms" | awk '

func CalDate( date_cd ) {

	jd_cd = int(date_cd[j_date_i] + 0.5); #	/* integer julian date */
	frac_cd = date_cd[j_date_i] + 0.5 - jd_cd + 1.0e-10; #/* day fraction */
	ka_cd = int(jd_cd);
	if ( jd_cd >= 2299161 )
	{
		ialp_cd = int(( jd_cd - 1867216.25 ) / ( 36524.25 ));
		ka_cd = int(jd_cd + 1 + ialp_cd - ( int(ialp_cd / 4) ));
	}
	kb_cd = ka_cd + 1524;
	kc_cd = int(( kb_cd - 122.1 ) / 365.25);
	kd_cd = int(kc_cd * 365.25);
	ke_cd = int(( kb_cd - kd_cd ) / 30.6001);
	date_cd[day_i] = kb_cd - kd_cd - int( ke_cd * 30.6001 );

	if ( ke_cd > 13 ) { date_cd[month_i] = ke_cd - 13;
	} else { date_cd[month_i] = ke_cd - 1; }

	if ( (date_cd[month_i] == 2) && (date_cd[day_i] > 28) ) date_cd[day_i] = 29;

	if ( (date_cd[month_i] == 2) && (date_cd[day_i] == 29) && (ke_cd == 3) ) {
		date_cd[year_i] = kc_cd - 4716;
	} else { if ( date_cd[month_i] > 2 ) { date_cd[year_i] = kc_cd - 4716;
		} else { date_cd[year_i] = kc_cd - 4715; }
	}

	date_cd[d_hour_i] = frac_cd * 24.0;	#/* hour */
	date_cd[i_hour_i] = int(date_cd[d_hour_i]);
	date_cd[d_minute_i] = ( date_cd[d_hour_i] - date_cd[i_hour_i] ) * 60.0; # /* minute */
	date_cd[i_minute_i] = int(date_cd[d_minute_i]);
	date_cd[second_i] = 60.0 * \
		(date_cd[d_minute_i] - date_cd[i_minute_i] ); #/* second */
	date_cd[weekday_i] = int((jd_cd + 1) % 7);	# /* day of week */
	if ( date_cd[year_i] == int(((int(date_cd[year_i] / 4)) * 4)) ) {
		date_cd[day_of_year_i] = ( ( 275 * date_cd[month_i] ) / 9) \
			- ((date_cd[month_i] + 9) / 12) \
			+ date_cd[day] - 30;
	} else {
		date_cd[day_of_year_i] = int( ( 275 * date_cd[month_i] ) / 9) \
			- int(((date_cd[month_i] + 9) / 12) * 2) \
			+ date_cd[day] - 30;
	}
	return( date_cd[year_i] );
}	#	/*	end of	 int CalDate( date )	*/

# /*
#  *	juldat computes the julian decimal date (j_date) from
#  *	the gregorian (or Julian) calendar date.
#  *	for astronomical purposes, The Gregorian calendar reform occurred
#  *	on 15 Oct. 1582.  This is 05 Oct 1582 by the julian calendar.
#  *	Input:  a ut_instant structure pointer where Day, Month, Year and
#  *		i_hour, i_minute, second have been set for the date
#  *		in question.
#  *
#  *	Output: the j_date and weekday elements of the structure will be set.
#  *		Also, the return value of the function will be the j_date too.
#  *
#  *	Reference: Astronomial formulae for calculators, meeus, p 23
#  *	from fortran program by F. Espenak - April 1982 Page 276,
#  *	50 Year canon of solar eclipses: 1986-2035
#  */

# double juldat( date )

func juldat( date_jd ) {

	# /* decimal day fraction	*/
	frac_jd = (date_jd[i_hour_i]/ 24.0) \
		+ (date_jd[i_minute_i] / 1440.0) \
		+ (date_jd[second_i] / 86400.0);
	# /* convert date to format YYYY.MMDDdd	*/
	gyr_jd = date_jd[year_i] + (0.01 * date_jd[month_i]) \
		+ (0.0001 * date_jd[day_i]) \
		+ (0.0001 * frac_jd) + 1.0e-9;
	# /* conversion factors */
	if ( date_jd[month_i] <= 2 )
	{
		iy0_jd = date_jd[year_i] - 1;
		im0_jd = date_jd[month_i] + 12;
	}
	else
	{
		iy0_jd = date_jd[year_i];
		im0_jd = date_jd[month_i];
	}
	ia_jd = int(iy0_jd / 100);
	ib_jd = int(2 - ia_jd + int(ia_jd / 4));
	# /* calculate julian date	*/
	if ( date_jd[year_i] <= 0 )
		jd_jd = int(((365.25 * iy0_jd) - 0.75)) \
			+ int((30.6001 * (im0_jd + 1) )) \
			+ int(date_jd[day_i] + 1720994);
	else
		jd_jd = int((365.25 * iy0_jd)) \
			+ int((30.6001 * (im0_jd + 1))) \
			+ int(date_jd[day_i] + 1720994);
	if ( gyr_jd >= 1582.1015 )	# /* on or after 15 October 1582	*/
		jd_jd += ib_jd;
	date_jd[j_date_i] = jd_jd + frac_jd + 0.5;
	jd_jd = int((date_jd[j_date_i] + 0.5));
	date_jd[weekday_i] = int((jd_jd + 1) % 7);
	return( date_jd[j_date_i] );
}	#	/*	end of	double juldat( date )	*/

func PrintDate ( d ) {
	printf( "%.6f\n", d[j_date_i] );
}
func ZeroDate ( d ) {
	d[j_date_i] = 0.0;
	d[year_i] = 0; d[month_i] = 0; d[day_i] = 0; d[i_hour_i] = 0;
	d[i_minute_i] = 0; d[second_i] = 0; d[d_hour_i] = 0.0
	d[d_minute_i] = 0.0; d[weekday_i] = 0; d[day_of_year_i] = 0;
}
#
#	Define our structure with array indices
#
BEGIN { j_date_i = 1; year_i = 2; month_i = 3; day_i = 4;
	i_hour_i = 5; i_minute_i = 6; second_i = 7; d_hour_i = 8;
	d_minute_i = 9; weekday_i = 10; day_of_year_i = 11;

	test_jd[j_date_i] = 0.0;
	ZeroDate(test_jd);
}
{
	n=split($0,a," ")
	m=split(a[1],ymd,"-")
	o=split(a[2],hms,":")
	test_jd[year_i] = ymd[1];
	test_jd[month_i] = ymd[2];
	test_jd[day_i] = ymd[3];
	test_jd[i_hour_i] = hms[1];
	test_jd[i_minute_i] = hms[2];
	test_jd[second_i] = hms[3];
	test_jd[j_date_i] = 0.0;
	juldat( test_jd );
	PrintDate( test_jd );
}'
