<!-- <%

/* Required files:
	Toolkit.js
*/

// to convert Earth time to Mars:
var MILLISECONDS_PER_SOL = 88775244;

// units for decimal clock:
var MILS_PER_SOL = 1000;
var BEATS_PER_MIL = 100;

// units for timeslip clock:
var HOURS_PER_SOL = 24.65979;
var MINUTES_PER_HOUR = 60;
var SECONDS_PER_MINUTE = 60;

// units for stretched clock:
var SPELLS_PER_SOL = 24;
var MOMENTS_PER_SPELL = 60;
var JIFFIES_PER_MOMENT = 60;

// start date for Viking 1:
//var MARS_START = Date.UTC(1975, 11, 17, 23, 46, 12, 0).valueOf();
// start date for Martian northern vernal equinox in 1609, the year
// Astronomy Novia was published by Johannes Kepler, and also the year
// the telescope was first used for astronomy, by Galileo Galilei:
var MARS_START = Date.UTC(1609, 02, 8, 16, 41, 40, 400).valueOf();


function IsLeapMir(mir)
// returns true if a leap mir:
{
	// if mir is not divisible by 10 then the rule is very simple:
	// it's a leap year if odd, and not a leap year if even:
	if (mir % 10 != 0)
		return (mir % 2 == 1);
	// now we know mir is divisble by 10, must investigate further:
	// if mir divisible by 1000, then it's a leap mir:
    if (mir % 1000 == 0)
		return true;
	// if mir divisible by 100 then it's not a leap mir:
    if (mir % 100 == 0)
		return false;
	// otherwise it is a leap mir:
    return true;
}


function SolsInMir(mir)
// returns number of sols in mir specified by mir:
{
	if (IsLeapMir(mir))
		return 669;
	else
		return 668;
}


function SolsInMonth(month, mir)
// returns number of sols in month, specified by month and mir:
{
	// Ophiuchus is a special case:
	if (month == 24)
	{
		if (IsLeapMir(mir))
			return 25;
		else
			return 24;
	}
	else
		return 28;
}


function MarsDate(milliseconds)
{
	// Constructor for MarsDate object.
	// input: time in milliseconds (standard return from (new Date()).valueOf())
	// output: object representing Mars date and time

	// if no parameter provided, use current time:
	if (typeof(milliseconds) == 'undefined')
		milliseconds = (new Date()).valueOf();

	// convert the milliseconds to number of sols since MARS_START:
	var sols = (milliseconds - MARS_START) / MILLISECONDS_PER_SOL;

	// which mir:
	var Mir = 0;
	var MirLen;
	if (sols < 0) // it's a negative mir
	{
		while (sols < 0)
		{
			Mir--;
			MirLen = SolsInMir(Mir);
			sols += MirLen;
		}
	}
	else // it's 0 or +ve mir:
	{
		MirLen = SolsInMir(Mir)
		// if we have more sols left than there are in current mir,
		// subtract the number of sols in the current mir from the remainder,
		// and go to the next mir:
		while (sols > MirLen)
		{
			sols -= MirLen;
			Mir++;
			MirLen = SolsInMir(Mir);
		}
	}
	this.Mir = Mir;

	// which month:
	// start in Sagittarius (month 1):
	var Month = 1;
	var MonthLen = SolsInMonth(Month, Mir);
	while (sols > MonthLen)
	{
		// goto next month:
		sols -= MonthLen;
		Month++;
		MonthLen = SolsInMonth(Month, Mir);
	}
	this.Month = Month;

	// get whole number of remaining sols
	var nWholeSols = Math.floor(sols);
	this.Sol = nWholeSols + 1; // add 1 because if there is 0 whole sols left we are in the first sol of the month

	// the fractional part of the sol is whatever's left:
	sols -= nWholeSols;
	this.Frac = sols;
}


function MarsDate_valueOf(MDate)
{
	// ** currently only programmed for +ve mirs:
	// convert MDate to sols:
	var sols = 0;
	for (var mir = 0; mir < MDate.Mir; mir++)
		sols += SolsInMir(mir);
	sols += 28 * (MDate.Month - 1) + (MDate.Sol - 1) + MDate.Frac;
	// convert to milliseconds:
	return sols * MILLISECONDS_PER_SOL + MARS_START;
}


function MarsMonth(month)
// returns the month name given the month number (1..24):
{
	switch (month)
	{
		case 1: return "Sagittarius";
		case 2: return "Aquila";
		case 3: return "Capricornus";
		case 4: return "Grus";
		case 5: return "Aquarius";
		case 6: return "Pegasus";
		case 7: return "Pisces";
		case 8: return "Cetus";
		case 9: return "Aries";
		case 10: return "Perseus";
		case 11: return "Taurus";
		case 12: return "Orion";
		case 13: return "Gemini";
		case 14: return "Monoceros";
		case 15: return "Cancer";
		case 16: return "Hydra";
		case 17: return "Leo";
		case 18: return "Corvus";
		case 19: return "Virgo";
		case 20: return "Bootes";
		case 21: return "Libra";
		case 22: return "Lupus";
		case 23: return "Scorpius";
		case 24: return "Ophiuchus";
	}
}

function AbbrevMarsMonth(month)
// returns the month name given the month number (1..24):
{
	switch (month)
	{
		case 1: return "Sgr";
		case 2: return "Aql";
		case 3: return "Cap";
		case 4: return "Gru";
		case 5: return "Aqr";
		case 6: return "Peg";
		case 7: return "Psc";
		case 8: return "Cet";
		case 9: return "Ari";
		case 10: return "Per";
		case 11: return "Tau";
		case 12: return "Ori";
		case 13: return "Gem";
		case 14: return "Mon";
		case 15: return "Cnc";
		case 16: return "Hya";
		case 17: return "Leo";
		case 18: return "Crv";
		case 19: return "Vir";
		case 20: return "Boo";
		case 21: return "Lib";
		case 22: return "Lup";
		case 23: return "Sco";
		case 24: return "Oph";
	}
}

function SolName(nSolOfMonth)
// returns the sol name given the sol number (1..28):
{
	nSolOfWeek = (nSolOfMonth - 1) % 7 + 1;
	switch (nSolOfWeek)
	{
		case 1: return "Sunsol";
		case 2: return "Phobosol";
		case 3: return "Terrasol";
		case 4: return "Mercusol";
		case 5: return "Jovisol";
		case 6: return "Venusol";
		case 7: return "Deimosol";
	}
}


///////////////////////////////////////////////////////////////////////////////////////////////////
// functions to format Mars dates and times:

function FormatMarsDate(MDate)
{
	return ThreeDigits(MDate.Mir) + "-" + AbbrevMarsMonth(MDate.Month) + "-" + TwoDigits(MDate.Sol);
}


function FormatMarsTimeDecimal(MDate)
{
	var frac = MDate.Frac * MILS_PER_SOL;
	var Mils = Math.floor(frac);
	frac = (frac - Mils) * BEATS_PER_MIL;
	var Beats = Math.floor(frac);
	return ThreeDigits(Mils) + "." + TwoDigits(Beats);
}


function FormatMarsTimeTimeslip(MDate)
{
	var frac = MDate.Frac * HOURS_PER_SOL;
	var Hours = Math.floor(frac);
	frac = (frac - Hours) * MINUTES_PER_HOUR;
	var Minutes = Math.floor(frac);
	frac = (frac - Minutes) * SECONDS_PER_MINUTE;
	var Seconds = Math.floor(frac);
	return TwoDigits(Hours) + ":" + TwoDigits(Minutes) + ":" + TwoDigits(Seconds);
}


function FormatMarsTimeStretched(MDate)
{
	var frac = MDate.Frac * SPELLS_PER_SOL;
	var Spells = Math.floor(frac);
	frac = (frac - Spells) * MOMENTS_PER_SPELL;
	var Moments = Math.floor(frac);
	frac = (frac - Moments) * JIFFIES_PER_MOMENT;
	var Jiffies = Math.floor(frac);
	return TwoDigits(Spells) + ":" + TwoDigits(Moments) + ":" + TwoDigits(Jiffies);
}


///////////////////////////////////////////////////////////////////////////////////////////////////
// functions to convert time of day, outputting formatted strings:

function ConvertEarthTimeToMarsTime(nHours)
// returns a string representation of Mars time given hours:
{
	return FormatMarsTime(nHours * nMilsPerHour);
}


function ConvertMarsTimeToEarthTime(nMils)
// returns a string representation of Earth time given nMils:
{
	return FormatEarthTime(nMils / nMilsPerHour);
}

// %> -->
