#!/usr/local/bin/perl
###############################################################################
#		Written By:  Torquil Gault (torquil_gault@hotmail.com) C) 2000-
#
#	This program is free software; you can redistribute it and/or
#	modify it under the terms of the GNU General Public License
#	as published by the Free Software Foundation; either version 2
#	of the License, or (at your option) any later version.
#	
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#	
#	You should have received a copy of the GNU General Public License
#	along with this program; if not, write to the Free Software
#	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
###############################################################################

#
###############################################################################
@MonthDays = ([0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
				  [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]);
@TotalDays = ([0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365],
				  [0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]);

###############################################################################
#  Is the year passed to it a leap year ???
sub IsLeapYear {
	if ($_[0] % 4 == 0 && ($_[0] % 100 != 0 || $_[0] % 400 == 0)) {
		return $True;
	}
	return $False;
}

###############################################################################
# Converts a date to the no. of days since 1/1/0000. It can be called with
# "date" or dd,mm,yyyy
sub DateToDays {
	my $np = @_; 			# No of params
	my $d = $m = $y = 0;
	if ($np == 3) {		# Check the no of parameters passed
		($d, $m, $y) = @_;
	}
	elsif ($np == 1) {
		($d, $m, $y) = split($Date_Delimiters, $_[0]);
	}
	else {
		return 0;
	}
	my $total = 0;

	my $isLeap = &IsLeapYear($y);
	my $mon = $MonthDays[$isLeap][$m];

	if ($d < 1 || $d > $mon) {		# Quick sanity check of the date
		return 0;
	}
	my $yr = int($y / 4);
	$total += $yr * 1461;
	$yr *= 4;

	while ($yr < $y) {
		$isLeap = &IsLeapYear($yr);
		$total += (365 + $isLeap);
		$yr++;
	}
	$isLeap = &IsLeapYear($y);
	$total += $TotalDays[$isLeap][$m];
	$total += $d;

	dprint("dateToDays: $d/$m/$y = $total");
	return $total;
}
	
###############################################################################
# Converts a Long to a date. Starts from 1/1/0000.
sub DaysToDate {
	my $total = $_[0];
	my $yr = int($total / 1461) * 4;
	my $daysleft = int($total % 1461);
	my $isLeap = &IsLeapYear($yr);
	if ($daysleft == 0 && $isLeap == 1) {
		$yr --;
		$isLeap = 0;
		$daysleft = 365;
	}
	my $daysayear = $isLeap + 365;
	while ($daysleft > $daysayear) {
		$yr ++;
		$daysleft -= $daysayear;
		$isLeap = &IsLeapYear($yr);
		$daysayear = $isLeap + 365;
	}
	my $mon = 1;
	while ($daysleft > $MonthDays[$isLeap][$mon]) {
		$daysleft -= $MonthDays[$isLeap][$mon];
		$mon ++;
	}
	dprint("daysToDate: $_[0] = $daysleft/$mon/$yr");
	return "$daysleft/$mon/$yr";
}

###############################################################################
# add/subtract days from a date. It can be called with "date", no_days or dd,mm,yy,no_days
sub dateMaths {
	my $np = @_;		# number of param's passed
	my $date = "";
	my $nd = 0;
	if ($np == 2) {	# assume date, no_days
		($date, $nd) = @_;
		dprint("dateMaths: $date, $nd");
		$nd = &DateToDays($date) + $nd;
	}
	elsif ($np == 4) {	# assume dd,mm,yy,no_days
		$nd = $_[3];
		dprint("dateMaths: $_[0]/$_[1]/$_[2], $nd");
		$nd = &DateToDays($_[0], $_[1], $_[2]) + $nd;
	}

	return &DaysToDate($nd);
}
