/*
 *	$Id: dbd.c,v 1.5 2005/10/06 21:24:25 hiram Exp $
 *
 *	Copyright (c) 1986-2005, Hiram Clawson - email: 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. 
 */
/*
 *
 *	dbd - days between dates.
 *	dbd - no arguments, do nothing at all
 *	dbd <julian decimal date>
 *		with one julian decimal date, calculate days between now
 *		and that date.
 *	dbd <julian decimal date> <julian decimal date>
 *		with two julian decimal dates, calculate days between those
 *		two dates.
 *
 */

#include	<stdio.h>
#include  <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include  <time.h>
#include <math.h>
#include "jday.h"

extern char version[];
extern char patchlevel[];
extern char date[];
extern char jday_copyright[];

static void
Version() {
fprintf(stderr, "dbd - version %s - %s\n", version, date );
fprintf(stderr, "\t%s\n", jday_copyright );
}

static void
Usage() {
fprintf(stderr, "usage: dbd [-[-]h[elp]] [-[-]v[ersion]] <julian date> [<julian date>]\n" );
fprintf(stderr, "\t- Calculate days between dates.\n" );
fprintf(stderr, "\t- One date supplied, calculate between then and now\n" );
fprintf(stderr, "\t- Two dates supplied, calculate between the two dates\n" );
fprintf(stderr, "\t- -h --h -help --help - show this help message\n" );
fprintf(stderr, "\t- -v --v -version --version - show version\n" );
fprintf(stderr, "\t- no arguments, do nothing\n" );
Version();
}

int
main( argc, argv )
int argc;
char * argv[];
{
	int i;
	double T0, T1;
	double ET;
	int ET_days;
	int ET_months;
	int ET_years;
  	time_t now_time;
	struct tm *ut_time;
	struct ut_instant now;
	struct ut_instant then;
	struct ut_instant previous_month;
	char * cp;

	(void) putenv("TZ=GMT");
	time ( & now_time);
	ut_time = localtime  (& now_time);

	now.year = ut_time->tm_year + 1900;;
	now.month = ut_time->tm_mon + 1;
	now.day = ut_time->tm_mday;
	now.i_hour = ut_time->tm_hour;
	now.i_minute = ut_time->tm_min;
	now.second = (double) ut_time->tm_sec;
	now.d_hour = (double) ut_time->tm_hour;
	now.d_minute = (double) ut_time->tm_min;
	now.weekday = ut_time->tm_wday;
	now.day_of_year = ut_time->tm_yday;

	(void) JulDate( & now );
printf ("the ut instant now is: %d/%02d/%02d %02d:%02d:%02d %.6f JD\n",
	now.year, now.month, now.day, now.i_hour, now.i_minute,
	(int)(now.second + 0.5), now.j_date );

	if ( argc > 1 ) {
		/*	check for either -h or -v	*/
		for ( i = 1; i < argc; ++i ) {
			if ( (char *) NULL != (cp =
			strstr((const char *)argv[i], (const char *) "-h") ) ){
				Usage();
				exit(0);
				/*	NOTREACHED	*/
			}
			if ( (char *) NULL != (cp =
			strstr((const char *)argv[i], (const char *) "-v") ) ){
				Version();
				exit(0);
				/*	NOTREACHED	*/
			}
		}
		switch ( argc ) {
			case 3:
				T0 = atof( argv[1] );
				T1 = atof( argv[2] );
				if ( T0 > T1 ) {
					now.j_date = T0;
					then.j_date = T1;
				} else {
					now.j_date = T1;
					then.j_date = T0;
				}
				break;
			case 2:
				T0 = atof( argv[1] );
				T1 =  now.j_date;
				break;
			case 1:
				exit(0);
				/*	NOTREACHED	*/
				break;
			default:
				Usage();
				exit( 0 );
				/*	NOTREACHED	*/
				break;
		}
	} else {
		exit( 0 );
		/*	NOTREACHED	*/
	}

	/*	ensure 'now' is later than 'then'	*/

	if ( T0 > T1 ) {
		now.j_date = T0;
		then.j_date = T1;
		ET = T0 - T1;	/*	days	*/
	} else {
		now.j_date = T1;
		then.j_date = T0;
		ET = T1 - T0;	/*	days	*/
	}

	/*	calculate calendar dates from julian dates	*/

	(void) CalDate( & now );
	(void) CalDate( & then );
printf (" now time: %d/%02d/%02d %02d:%02d:%02d %.6f JD\n",
	now.year, now.month, now.day, now.i_hour, now.i_minute,
	(int)(now.second + 0.5), now.j_date );
printf ("then time: %d/%02d/%02d %02d:%02d:%02d %.6f JD\n",
	then.year, then.month, then.day, then.i_hour, then.i_minute,
	(int)(then.second + 0.5), then.j_date );

	printf ("%.6f days =", ET );

	/*	Now, do the difference in years, months, days	*/

	/*	If the day of the month now is earlier than the day
	 *	of the month then, we need to count the days from the
	 *	last month to now.  Otherwise, it is a simple subtraction.
	 */
	if ( now.day < then.day ) {
		/*	to get the last day of the previous month,
		 *	subtract day of month now from now's julian date.
		 *	That would be the jd of day 0 of this month now.
		 *	That is equivalent to the last day of the previous
		 *	month.
		 */
		previous_month.j_date = now.j_date - (double) now.day;
		(void) CalDate( & previous_month );
		ET_days = previous_month.day + now.day - then.day;
		if ( previous_month.month < then.month ) {
			ET_months = 12 + previous_month.month - then.month;
			ET_years = previous_month.year - then.year - 1;
		} else {
			ET_months = previous_month.month - then.month;
			ET_years = previous_month.year - then.year;
		}
	} else {
		ET_days = now.day - then.day;
		if ( now.month < then.month ) {
			ET_months = 12 + now.month - then.month;
			ET_years = now.year - then.year - 1;
		} else {
			ET_months = now.month - then.month;
			ET_years = now.year - then.year;
		}
	}

	if ( ET_years ) {
		if ( 1 == ET_years ) {
			printf ( " %d year", ET_years );
		} else {
			printf ( " %d years", ET_years );
		}
	}
	if ( ET_months ) {
		if ( 1 == ET_months ) {
			printf ( " %d month", ET_months );
		} else {
			printf ( " %d months", ET_months );
		}
	}
	if ( ET_days ) {
		if ( 1 == ET_days ) {
			if ( ET_years || ET_months ) {
				printf ( " and a day" );
			} else {
				printf ( " one day" );
			}
		} else {
			if ( ET_years || ET_months ) {
				printf ( " and %d days", ET_days );
			} else {
				printf ( " %d days", ET_days );
			}
		}
	}
	printf ("\n");

	exit( 0 );
	/*	NOTREACHED	*/
}


syntax highlighted by Code2HTML, v. 0.9.1