﻿// (C) Azurant, LLC 2007
//
// All rights are reserved. Reproduction or transmission in whole or in part, in
// any form or by any means, electronic, mechanical or otherwise, is prohibited
// without the prior written permission of the copyright owner.
//
// Filename: Date.js
//
// DATE     NAME    COMMENT
// 02/23/07 MIJ     Created file.
//
// This file contains date functions for use with the Eclarix system.
//
//////////////////////////////////////////////////////////////////////////////

// Validates a date, returning true or false depending on whether the date is valid.
// value: String value to validate.
// format: Date format. Valid values are "MM/dd/yyyy" and "M/d/yyyy".
// Returns: boolean
function ValidDate(value, format)
{
	var valid = false;
	
	if (value != null)
	{
		if (format == null)
		{
			alert("Date format string is NULL.");
		}
		
		if (format == "MM/dd/yyyy" || format == "M/d/yyyy")
		{
			if (value.length < 8) // shortest we allow is M/d/yyyy
			{
				return false;
			}
			
			var dateComponents = value.split("/");
			
			if (dateComponents == null || dateComponents.length != 3)
			{
				return false;
			}
			
			var monthComponent = dateComponents[0];
			var dateComponent = dateComponents[1];
			var yearComponent = dateComponents[2];
			
			if (monthComponent == null || Trim(monthComponent).length == 0 || isNaN(monthComponent) || 
					dateComponent == null || Trim(dateComponent).length == 0 || isNaN(dateComponent) || 
					yearComponent == null || Trim(yearComponent).length == 0 || isNaN(yearComponent))
			{
				return false;
			}
			
			if (yearComponent.length != 4)
			{
				return false;
			}
			
			var monthValue = parseInt(monthComponent, 10);
			var dateValue = parseInt(dateComponent, 10);
			var yearValue = parseInt(yearComponent, 10);
			
			if (monthValue < 1 || monthValue > 12 || dateValue < 1 || dateValue > 31 || yearValue < 0)
			{
				return false;
			}
			
			var maxDaysInMonth = GetDaysInMonthYear(monthValue, yearValue);
			if (dateValue > maxDaysInMonth)
			{
				return false;
			}
			
			valid = true;
		}
		else
		{
			alert("Date format string is invalid: " + format + ".");
		}
	}
	
	return valid;
}

// Validates a time string, in 12 or 24 hour formats
// value: String value to validate.
// format: Time format. Valid values are "HH:mm", "HHmm", "hh:mm tt", "h:m tt".
// Returns: boolean
function ValidTime(value, format)
{
	var valid = false;
	
	if (value != null)
	{
		if (format == null)
		{
			alert("Time format string is NULL.");
		}

		if (format == "HH:mm")
		{
			if (value.length < 4) // shortest we allow is H:mm
			{
				return false;
			}
			
			var timeComponents = value.split(":");
			
			if (timeComponents == null || timeComponents.length != 2)
			{
				return false;
			}
			
			var hourComponent = timeComponents[0];
			var minuteComponent = timeComponents[1];

			if (hourComponent == null || Trim(hourComponent).length == 0 || isNaN(hourComponent) || 
					minuteComponent == null || Trim(minuteComponent).length == 0 || isNaN(minuteComponent))
			{
				return false;
			}
			
			if (hourComponent < 0 || hourComponent > 23 || minuteComponent < 0 || minuteComponent > 59)
			{
				return false;
			}
			
			valid = true;
		}
		else if (format == "HHmm")
		{
		    if (value.length != 4)
		    {
		        return false;
		    }
		    
		    var hourComponent = value.substring(0, 2);
		    var minuteComponent = value.substring(2, 4);
		    
			if (hourComponent == null || Trim(hourComponent).length == 0 || isNaN(hourComponent) || 
					minuteComponent == null || Trim(minuteComponent).length == 0 || isNaN(minuteComponent))
			{
				return false;
			}
			
			if (hourComponent < 0 || hourComponent > 23 || minuteComponent < 0 || minuteComponent > 59)
			{
				return false;
			}
			
			valid = true;		    
		}
		else if (format == "hh:mm tt" || format == "h:m tt")
		{
			if (value.length < 7) // shorted we allow is h:mm tt
			{
				return false;
			}
			
			var timeComponents = value.split(":");
			
			if (timeComponents == null || timeComponents.length != 2)
			{
				return false;
			}			
			
			var hourComponent = timeComponents[0];
			
			if (hourComponent == null || Trim(hourComponent).length == 0 || isNaN(hourComponent))
			{
				return false;
			}
			
			var minuteDayComponent = timeComponents[1];
			
			if (minuteDayComponent == null || Trim(minuteDayComponent).length == 0)
			{
				return false;
			}
			
			var minuteDayComponents = minuteDayComponent.split(" ");
			
			if (minuteDayComponents == null || minuteDayComponents.length != 2)
			{
				return false;
			}
			
			var minuteComponent = minuteDayComponents[0];
			var dayComponent = minuteDayComponents[1];
			
			if (minuteComponent == null || Trim(minuteComponent).length == 0 || isNaN(minuteComponent) ||
				dayComponent == null || Trim(dayComponent).length == 0)
			{
				return false;
			}
			
			dayComponent = dayComponent.toUpperCase();
			
			if (dayComponent != "AM" && dayComponent != "PM")
			{
				return false;
			}
			
			var hourValue = parseInt(hourComponent, 10);
			var minuteValue = parseInt(minuteComponent, 10);			
			
			if (hourValue < 1 || hourValue > 12 || minuteValue < 0 || minuteValue > 59)
			{
				return false;
			}			
			
			valid = true;
		}
		else
		{
			alert("Time format string is invalid: " + format + ".");
		}
	}
	
	return valid;
}

// Returns the number of days in the month - month is 1-based index
// month: Month - 1-based index.
// year: 4-digit year.
// Returns: int
function GetDaysInMonthYear(month, year) 
{
	var days = -1;

	switch (month) 
	{
		case 1: case 3: case 5: case 7: case 8: case 10: case 12:
			days = 31;
			break;
		case 4: case 6: case 9: case 11:
			days = 30;
			break;
		case 2:
			/*
				Check for leap year ..
				1.Years evenly divisible by four are normally leap years, except for...
				2.Years also evenly divisible by 100 are not leap years, except for...
				3.Years also evenly divisible by 400 are leap years.
			*/
			if ((year % 4) == 0) 
			{
				if ((year % 100) == 0 && (year % 400) != 0)
					days = 28;
				else
					days = 29;
			}
			else
				days = 28;

			break;
		default:
			break;
	}

	return days;
}

// Returns the timezone name for the browser.
function GetTimezoneName() {
	var tmSummer = new Date(Date.UTC(2005, 6, 30, 0, 0, 0, 0));
	var so = -1 * tmSummer.getTimezoneOffset();
	var tmWinter = new Date(Date.UTC(2005, 12, 30, 0, 0, 0, 0));
	var wo = -1 * tmWinter.getTimezoneOffset();

	if (-660 == so && -660 == wo) return 'Pacific/Midway';
	if (-600 == so && -600 == wo) return 'Pacific/Tahiti';
	if (-570 == so && -570 == wo) return 'Pacific/Marquesas';
	if (-540 == so && -600 == wo) return 'America/Adak';
	if (-540 == so && -540 == wo) return 'Pacific/Gambier';
	if (-480 == so && -540 == wo) return 'US/Alaska';
	if (-480 == so && -480 == wo) return 'Pacific/Pitcairn';
	if (-420 == so && -480 == wo) return 'US/Pacific';
	if (-420 == so && -420 == wo) return 'US/Arizona';
	if (-360 == so && -420 == wo) return 'US/Mountain';
	if (-360 == so && -360 == wo) return 'America/Guatemala';
	if (-360 == so && -300 == wo) return 'Pacific/Easter';
	if (-300 == so && -360 == wo) return 'US/Central';
	if (-300 == so && -300 == wo) return 'America/Bogota';
	if (-240 == so && -300 == wo) return 'US/Eastern';
	if (-240 == so && -240 == wo) return 'America/Caracas';
	if (-240 == so && -180 == wo) return 'America/Santiago';
	if (-180 == so && -240 == wo) return 'Canada/Atlantic';
	if (-180 == so && -180 == wo) return 'America/Montevideo';
	if (-180 == so && -120 == wo) return 'America/Sao_Paulo';
	if (-150 == so && -210 == wo) return 'America/St_Johns';
	if (-120 == so && -180 == wo) return 'America/Godthab';
	if (-120 == so && -120 == wo) return 'America/Noronha';
	if (-60 == so && -60 == wo) return 'Atlantic/Cape_Verde';
	if (0 == so && -60 == wo) return 'Atlantic/Azores';
	if (0 == so && 0 == wo) return 'Africa/Casablanca';
	if (60 == so && 0 == wo) return 'Europe/London';
	if (60 == so && 60 == wo) return 'Africa/Algiers';
	if (60 == so && 120 == wo) return 'Africa/Windhoek';
	if (120 == so && 60 == wo) return 'Europe/Amsterdam';
	if (120 == so && 120 == wo) return 'Africa/Harare';
	if (180 == so && 120 == wo) return 'Europe/Athens';
	if (180 == so && 180 == wo) return 'Africa/Nairobi';
	if (240 == so && 180 == wo) return 'Europe/Moscow';
	if (240 == so && 240 == wo) return 'Asia/Dubai';
	if (270 == so && 210 == wo) return 'Asia/Tehran';
	if (270 == so && 270 == wo) return 'Asia/Kabul';
	if (300 == so && 240 == wo) return 'Asia/Baku';
	if (300 == so && 300 == wo) return 'Asia/Karachi';
	if (330 == so && 330 == wo) return 'Asia/Calcutta';
	if (345 == so && 345 == wo) return 'Asia/Katmandu';
	if (360 == so && 300 == wo) return 'Asia/Yekaterinburg';
	if (360 == so && 360 == wo) return 'Asia/Colombo';
	if (390 == so && 390 == wo) return 'Asia/Rangoon';
	if (420 == so && 360 == wo) return 'Asia/Almaty';
	if (420 == so && 420 == wo) return 'Asia/Bangkok';
	if (480 == so && 420 == wo) return 'Asia/Krasnoyarsk';
	if (480 == so && 480 == wo) return 'Australia/Perth';
	if (540 == so && 480 == wo) return 'Asia/Irkutsk';
	if (540 == so && 540 == wo) return 'Asia/Tokyo';
	if (570 == so && 570 == wo) return 'Australia/Darwin';
	if (570 == so && 630 == wo) return 'Australia/Adelaide';
	if (600 == so && 540 == wo) return 'Asia/Yakutsk';
	if (600 == so && 600 == wo) return 'Australia/Brisbane';
	if (600 == so && 660 == wo) return 'Australia/Sydney';
	if (630 == so && 660 == wo) return 'Australia/Lord_Howe';
	if (660 == so && 600 == wo) return 'Asia/Vladivostok';
	if (660 == so && 660 == wo) return 'Pacific/Guadalcanal';
	if (690 == so && 690 == wo) return 'Pacific/Norfolk';
	if (720 == so && 660 == wo) return 'Asia/Magadan';
	if (720 == so && 720 == wo) return 'Pacific/Fiji';
	if (720 == so && 780 == wo) return 'Pacific/Auckland';
	if (765 == so && 825 == wo) return 'Pacific/Chatham';
	if (780 == so && 780 == wo) return 'Pacific/Enderbury'
	if (840 == so && 840 == wo) return 'Pacific/Kiritimati';
	return 'US/Pacific';
}

function DateAdd(objDate, strInterval, intIncrement)
{
    if (typeof(objDate) == "string")
    {
        objDate = new Date(objDate);

        if (isNaN(objDate))
        {
	       // throw("DateAdd: Date is not a valid date");
	       return new Date("01/01/1900");
        }
    }
    else if (typeof(objDate) != "object" || objDate.constructor.toString().indexOf("Date()") == -1)
    {
        //throw("DateAdd: First parameter must be a date object");
        return new Date("01/01/1900");
    }

    if (strInterval != "M" && strInterval != "D" && strInterval != "Y" && strInterval != "h" && strInterval != "m" &&
            strInterval != "uM" && strInterval != "uD" && strInterval != "uY" && strInterval != "uh" &&
            strInterval != "um" && strInterval != "us")
        {
            //throw("DateAdd: Second parameter must be M, D, Y, h, m, uM, uD, uY, uh, um or us");
            return new Date("01/01/1900");
        }

    if (typeof(intIncrement) != "number")
    {
        //throw("DateAdd: Third parameter must be a number");
        return new Date("01/01/1900");
    }

    switch (strInterval)
    {
        case "M":
        objDate.setMonth(parseInt(objDate.getMonth()) + parseInt(intIncrement));
        break;

        case "D":
        objDate.setDate(parseInt(objDate.getDate()) + parseInt(intIncrement));
        break;

        case "Y":
        objDate.setYear(parseInt(objDate.getYear()) + parseInt(intIncrement));
        break;

        case "h":
        objDate.setHours(parseInt(objDate.getHours()) + parseInt(intIncrement));
        break;

        case "m":
        objDate.setMinutes(parseInt(objDate.getMinutes()) + parseInt(intIncrement));
        break;

        case "s":
        objDate.setSeconds(parseInt(objDate.getSeconds()) + parseInt(intIncrement));
        break;

        case "uM":
        objDate.setUTCMonth(parseInt(objDate.getUTCMonth()) + parseInt(intIncrement));
        break;

        case "uD":
        objDate.setUTCDate(parseInt(objDate.getUTCDate()) + parseInt(intIncrement));
        break;

        case "uY":
        objDate.setUTCFullYear(parseInt(objDate.getUTCFullYear()) + parseInt(intIncrement));
        break;

        case "uh":
        objDate.setUTCHours(parseInt(objDate.getUTCHours()) + parseInt(intIncrement));
        break;

        case "um":
        objDate.setUTCMinutes(parseInt(objDate.getUTCMinutes()) + parseInt(intIncrement));
        break;

        case "us":
        objDate.setUTCSeconds(parseInt(objDate.getUTCSeconds()) + parseInt(intIncrement));
        break;
    }

    return objDate;
}

var holidays = "";

function GetNextDayText(dt1, daysToAdd, excludeWeekends, excludeHolidays, format)
{
    var dt2text = "";
    
    var dt2 = GetNextDay(dt1, daysToAdd, excludeWeekends, excludeHolidays);
    
    if (dt2 != null)
    {
        if (format == "MM/dd/yyyy")
        {
            dt2text = (dt2.getMonth() + 1) + "/" + dt2.getDate() + "/" + dt2.getFullYear();
        }
    }
        
    return dt2text;
}

function GetNextDay(dt1, daysToAdd, excludeWeekends, excludeHolidays)
{
    if (typeof(dt1) == "string")
    {
        dt1 = new Date(dt1);

        if (isNaN(dt1))
        {
	       // throw("DateAdd: Date is not a valid date");
	       return new Date("01/01/1900");
        }
    }
    else if (typeof(dt1) != "object" || objDate.constructor.toString().indexOf("Date()") == -1)
    {
        //throw("DateAdd: First parameter must be a date object");
        return new Date("01/01/1900");
    }
    
    var dt2 = dt1;
    
    var daysAdded = 0;
    
    if (daysToAdd == 0)
    {
    	return dt2;
    }

    if (daysToAdd < 0)
    {
        var daysToAdd = daysToAdd * -1;
        
        do
        {
        	dt2 = DateAdd(dt2, "D", -1);
        	
		if (excludeWeekends)
		{
		    if (dt2.getDay() > 0 && dt2.getDay() < 6)
		    {
			    if (excludeHolidays)
			    {
				    var holiday = false;

				    if (holidays != null && holidays.length > 0)
				    {
				        var holidayTokens = holidays.split(",");

				        for (var i = 0; i < holidayTokens.length; i++)
				        {
					        var holidayStr = holidayTokens[i];

					        try
					        {
					            var holidayDate = new Date(holidayStr);

						        if (dt2.valueOf() == holidayDate.valueOf())
						        {
							        holiday = true;
							        break;
						        }            		            
					        }
					        catch (e)
					        {
					        }
				        }            		    
				    }

				    if (!holiday)
				    {
					    daysAdded++;
				    }
			    }
			    else
			    {
				    daysAdded++;
			    }
		    }
		}
		else
		{
		    daysAdded++;
		}        	
        	
        } while (daysAdded < daysToAdd);        
    }
    else
    {
	    do
	    {
		dt2 = DateAdd(dt2, "D", 1);

		if (excludeWeekends)
		{
		    if (dt2.getDay() > 0 && dt2.getDay() < 6)
		    {
			if (excludeHolidays)
			{
				var holiday = false;

				if (holidays != null && holidays.length > 0)
				{
				    var holidayTokens = holidays.split(",");

				    for (var i = 0; i < holidayTokens.length; i++)
				    {
					var holidayStr = holidayTokens[i];

					try
					{
					    var holidayDate = new Date(holidayStr);

								if (dt2.valueOf() == holidayDate.valueOf())
								{
									holiday = true;
									break;
								}            		            
					}
					catch (e)
					{
					}
				    }            		    
				}

				if (!holiday)
				{
					daysAdded++;
				}
			}
			else
			{
				daysAdded++;
			}
		    }
		}
		else
		{
		    daysAdded++;
		}

	    } while (daysAdded < daysToAdd);    
    }



    return dt2;
}

function DateLessThan(dt1, dt2)
{
	var dateBefore = false;
	
	try
	{
		if (typeof(dt1) == "string")
		{
			dt1 = new Date(dt1);
		}
		
		if (typeof(dt2) == "string")
		{
			dt2 = new Date(dt2);
		}
		
		dateBefore = dt1.getTime() < dt2.getTime();
	}
	catch (e) { }
	
	return dateBefore;
}

function DateGreaterThan(dt1, dt2)
{
	var dateAfter = false;
	
	try
	{
		if (typeof(dt1) == "string")
		{
			dt1 = new Date(dt1);
		}
		
		if (typeof(dt2) == "string")
		{
			dt2 = new Date(dt2);
		}
		
		dateAfter = dt1.getTime() > dt2.getTime();
	}
	catch (e) { }
	
	return dateAfter;
}
