<?php
/*********************************************************************************
 * The contents of this file are subject to the TimeTrex Public License Version
 * 1.1.0 ("License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.TimeTrex.com/TPL
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * All copies of the Covered Code must include on each user interface screen:
 *    (i) the "Powered by TimeTrex" logo and
 *    (ii) the TimeTrex copyright notice
 * in the same form as they appear in the distribution.  See full license for
 * requirements.
 *
 * The Original Code is: TimeTrex Open Source
 * The Initial Developer of the Original Code is TimeTrex Payroll Services
 * Portions created by TimeTrex are Copyright (C) 2004-2007 TimeTrex Payroll Services;
 * All Rights Reserved.
 *
 ********************************************************************************/
/*
 * $Revision: 2158 $
 * $Id: DateTimeTest.php 2158 2008-09-15 23:26:15Z ipso $
 * $Date: 2008-09-15 16:26:15 -0700 (Mon, 15 Sep 2008) $
 */
require_once('PHPUnit/Framework/TestCase.php');

class DateTimeTest extends PHPUnit_Framework_TestCase {

    public function __construct() {
        global $db, $cache;

        require_once('../includes/global.inc.php');
		require_once( Environment::getBasePath().'/classes/payroll_deduction/PayrollDeduction.class.php');

        $profiler = new Profiler( true );
        Debug::setBufferOutput(FALSE);
        Debug::setEnable(TRUE);

        if ( PRODUCTION != FALSE ) {
            echo "DO NOT RUN ON A PRODUCTION SERVER<br>\n";
            exit;
        }
    }

    public function setUp() {
        Debug::text('Running setUp(): ', __FILE__, __LINE__, __METHOD__,10);
        return TRUE;
    }

    public function tearDown() {
        Debug::text('Running tearDown(): ', __FILE__, __LINE__, __METHOD__,10);
        return TRUE;
    }

	function testDate_DMY_1() {
		Debug::text('Testing Date Format: d-M-y', __FILE__, __LINE__, __METHOD__,10);

		TTDate::setDateFormat('d-M-y');
		TTDate::setTimeZone('PST');
		TTDate::setTimeFormat('g:i A');

		$this->assertEquals( TTDate::parseDateTime('25-Feb-05'), 1109318400 );

		$this->assertEquals( TTDate::parseDateTime('25-Feb-05 8:09PM'), 1109390940 );
		$this->assertEquals( TTDate::parseDateTime('25-Feb-05 8:09 AM'), 1109347740 );
		$this->assertEquals( TTDate::parseDateTime('25-Feb-05 8:09:10 AM'), 1109347750 );
		$this->assertEquals( TTDate::parseDateTime('25-Feb-05 8:09:10 AM EST'), 1109336950 );

		$this->assertEquals( TTDate::parseDateTime('25-Feb-05 18:09'), 1109383740 );
		$this->assertEquals( TTDate::parseDateTime('25-Feb-05 18:09:10'), 1109383750 );
		$this->assertEquals( TTDate::parseDateTime('25-Feb-05 18:09:10 EST'), 1109372950 );


		//Fails on PHP 5.1.2 due to strtotime()
		//TTDate::setDateFormat('d/M/y');
		//TTDate::setTimeZone('PST');
		//TTDate::setTimeFormat('g:i A');

		//$this->assertEquals( TTDate::parseDateTime('25/Feb/05'), 1109318400 );

		//$this->assertEquals( TTDate::parseDateTime('25/Feb/05 8:09PM'), 1109390940 );
		//$this->assertEquals( TTDate::parseDateTime('25/Feb/05 8:09 AM'), 1109347740 );
		//$this->assertEquals( TTDate::parseDateTime('25/Feb/05 8:09:10 AM'), 1109347750 );
		//$this->assertEquals( TTDate::parseDateTime('25/Feb/05 8:09:10 AM EST'), 1109336950 );

		//$this->assertEquals( TTDate::parseDateTime('25/Feb/05 18:09'), 1109383740 );
		//$this->assertEquals( TTDate::parseDateTime('25/Feb/05 18:09:10'), 1109383750 );
		//$this->assertEquals( TTDate::parseDateTime('25/Feb/05 18:09:10 EST'), 1109372950 );


		TTDate::setDateFormat('d-M-Y');
		TTDate::setTimeZone('PST');
		TTDate::setTimeFormat('g:i A');

		$this->assertEquals( TTDate::parseDateTime('25-Feb-2005'), 1109318400 );

		$this->assertEquals( TTDate::parseDateTime('25-Feb-2005 8:09PM'), 1109390940 );
		$this->assertEquals( TTDate::parseDateTime('25-Feb-2005 8:09 AM'), 1109347740 );
		$this->assertEquals( TTDate::parseDateTime('25-Feb-2005 8:09:10 AM'), 1109347750 );
		$this->assertEquals( TTDate::parseDateTime('25-Feb-2005 8:09:10 AM EST'), 1109336950 );

		$this->assertEquals( TTDate::parseDateTime('25-Feb-2005 18:09'), 1109383740 );
		$this->assertEquals( TTDate::parseDateTime('25-Feb-2005 18:09:10'), 1109383750 );
		$this->assertEquals( TTDate::parseDateTime('25-Feb-2005 18:09:10 EST'), 1109372950 );

		//Fails on PHP 5.1.2 due to strtotime()

		//TTDate::setDateFormat('d/M/Y');
		//TTDate::setTimeZone('PST');
		//TTDate::setTimeFormat('g:i A');

		//$this->assertEquals( TTDate::parseDateTime('25/Feb/2005'), 1109318400 );

		//$this->assertEquals( TTDate::parseDateTime('25/Feb/2005 8:09PM'), 1109390940 );
		//$this->assertEquals( TTDate::parseDateTime('25/Feb/2005 8:09 AM'), 1109347740 );
		//$this->assertEquals( TTDate::parseDateTime('25/Feb/2005 8:09:10 AM'), 1109347750 );
		//$this->assertEquals( TTDate::parseDateTime('25/Feb/2005 8:09:10 AM EST'), 1109336950 );

		//$this->assertEquals( TTDate::parseDateTime('25/Feb/2005 18:09'), 1109383740 );
		//$this->assertEquals( TTDate::parseDateTime('25/Feb/2005 18:09:10'), 1109383750 );
		//$this->assertEquals( TTDate::parseDateTime('25/Feb/2005 18:09:10 EST'), 1109372950 );
	}

	function testDate_DMY_2() {
		Debug::text('Testing Date Format: dMY', __FILE__, __LINE__, __METHOD__,10);

		TTDate::setDateFormat('dMY');
		TTDate::setTimeZone('PST');
		TTDate::setTimeFormat('g:i A');

		$this->assertEquals( TTDate::parseDateTime('25Feb2005'), 1109318400 );

		$this->assertEquals( TTDate::parseDateTime('25Feb2005 8:09PM'), 1109390940 );
		$this->assertEquals( TTDate::parseDateTime('25Feb2005 8:09 AM'), 1109347740 );
		$this->assertEquals( TTDate::parseDateTime('25Feb2005 8:09:10 AM'), 1109347750 );
		$this->assertEquals( TTDate::parseDateTime('25Feb2005 8:09:10 AM EST'), 1109336950 );

		$this->assertEquals( TTDate::parseDateTime('25Feb2005 18:09'), 1109383740 );
		$this->assertEquals( TTDate::parseDateTime('25Feb2005 18:09:10'), 1109383750 );
		$this->assertEquals( TTDate::parseDateTime('25Feb2005 18:09:10 EST'), 1109372950 );
	}

	function testDate_DMY_3() {
		Debug::text('Testing Date Format: d-m-y', __FILE__, __LINE__, __METHOD__,10);

		TTDate::setDateFormat('d-m-y');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::parseDateTime('25-02-2005'), 1109318400 );
		$this->assertEquals( TTDate::parseDateTime('25-02-2005 8:09PM'), 1109390940 );
		$this->assertEquals( TTDate::parseDateTime('25-02-2005 8:09 AM'), 1109347740 );

		TTDate::setTimeFormat('g:i A T');
		$this->assertEquals( TTDate::parseDateTime('25-02-2005 8:09 AM EST'), 1109336940 );

		TTDate::setTimeFormat('G:i');
		$this->assertEquals( TTDate::parseDateTime('25-02-2005 18:09'), 1109383740 );
		$this->assertEquals( TTDate::parseDateTime('25-02-2005 18:09 EST'), 1109372940 );

		//
		// Different separator
		//

		TTDate::setDateFormat('d/m/y');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::parseDateTime('25/02/2005'), 1109318400 );
		$this->assertEquals( TTDate::parseDateTime('25/02/2005 8:09PM'), 1109390940 );
		$this->assertEquals( TTDate::parseDateTime('25/02/2005 8:09 AM'), 1109347740 );

		TTDate::setTimeFormat('g:i A T');
		$this->assertEquals( TTDate::parseDateTime('25/02/2005 8:09 AM EST'), 1109336940 );

		TTDate::setTimeFormat('G:i');
		$this->assertEquals( TTDate::parseDateTime('25/02/2005 18:09'), 1109383740 );
		$this->assertEquals( TTDate::parseDateTime('25/02/2005 18:09 EST'), 1109372940 );
	}

	function testDate_MDY_1() {
		Debug::text('Testing Date Format: m-d-y', __FILE__, __LINE__, __METHOD__,10);

		TTDate::setDateFormat('m-d-y');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::parseDateTime('02-25-2005'), 1109318400 );
		$this->assertEquals( TTDate::parseDateTime('02-25-05'), 1109318400 );

		$this->assertEquals( TTDate::parseDateTime('10-27-06'), 1161932400 );

		$this->assertEquals( TTDate::parseDateTime('02-25-2005 8:09PM'), 1109390940 );
		$this->assertEquals( TTDate::parseDateTime('02-25-2005 8:09 AM'), 1109347740 );

		TTDate::setTimeFormat('g:i A T');
		$this->assertEquals( TTDate::parseDateTime('02-25-2005 8:09 AM EST'), 1109336940 );

		TTDate::setTimeFormat('G:i');
		$this->assertEquals( TTDate::parseDateTime('02-25-2005 18:09'), 1109383740 );
		$this->assertEquals( TTDate::parseDateTime('02-25-2005 18:09 EST'), 1109372940 );

		//
		// Different separator
		//
		TTDate::setDateFormat('m/d/y');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::parseDateTime('02/25/2005'), 1109318400 );
		$this->assertEquals( TTDate::parseDateTime('02/25/2005 8:09PM'), 1109390940 );
		$this->assertEquals( TTDate::parseDateTime('02/25/2005 8:09 AM'), 1109347740 );

		TTDate::setTimeFormat('g:i A T');
		$this->assertEquals( TTDate::parseDateTime('02/25/2005 8:09 AM EST'), 1109336940 );

		TTDate::setTimeFormat('G:i');
		$this->assertEquals( TTDate::parseDateTime('02/25/2005 18:09'), 1109383740 );
		$this->assertEquals( TTDate::parseDateTime('02/25/2005 18:09 EST'), 1109372940 );
	}

	function testDate_MDY_2() {
		Debug::text('Testing Date Format: M-d-y', __FILE__, __LINE__, __METHOD__,10);

		TTDate::setDateFormat('M-d-y');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::parseDateTime('Feb-25-2005'), 1109318400 );
		$this->assertEquals( TTDate::parseDateTime('Feb-25-05'), 1109318400 );
		$this->assertEquals( TTDate::parseDateTime('Feb-25-2005 8:09PM'), 1109390940 );
		$this->assertEquals( TTDate::parseDateTime('Feb-25-2005 8:09 AM'), 1109347740 );

		TTDate::setTimeFormat('g:i A T');
		$this->assertEquals( TTDate::parseDateTime('Feb-25-2005 8:09 AM EST'), 1109336940 );

		TTDate::setTimeFormat('G:i');
		$this->assertEquals( TTDate::parseDateTime('Feb-25-2005 18:09'), 1109383740 );
		$this->assertEquals( TTDate::parseDateTime('Feb-25-2005 18:09 EST'), 1109372940 );
	}

	function testDate_MDY_3() {
		Debug::text('Testing Date Format: m-d-y (two digit year)', __FILE__, __LINE__, __METHOD__,10);

		TTDate::setDateFormat('m-d-y');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::parseDateTime('02-25-05'), 1109318400 );
		$this->assertEquals( TTDate::parseDateTime('02-25-05 8:09PM'), 1109390940 );
		$this->assertEquals( TTDate::parseDateTime('02-25-05 8:09 AM'), 1109347740 );

		TTDate::setTimeFormat('g:i A T');
		$this->assertEquals( TTDate::parseDateTime('02-25-05 8:09 AM EST'), 1109336940 );

		TTDate::setTimeFormat('G:i');
		$this->assertEquals( TTDate::parseDateTime('02-25-05 18:09'), 1109383740 );
		$this->assertEquals( TTDate::parseDateTime('02-25-05 18:09 EST'), 1109372940 );

		//Try test before 1970, like 1920
		$this->assertEquals( TTDate::parseDateTime('02-25-20'), -1573142400 );
		$this->assertEquals( TTDate::parseDateTime('02-25-20 8:09PM'), -1573069860);
		$this->assertEquals( TTDate::parseDateTime('02-25-20 8:09 AM'), -1573113060 );

	}


	function testDate_YMD_1() {
		Debug::text('Testing Date Format: Y-m-d', __FILE__, __LINE__, __METHOD__,10);

		TTDate::setDateFormat('Y-m-d');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::parseDateTime('2005-02-25'), 1109318400 );
		$this->assertEquals( TTDate::parseDateTime('05-02-25'), 1109318400 );
		$this->assertEquals( TTDate::parseDateTime('2005-02-25 8:09PM'), 1109390940 );
		$this->assertEquals( TTDate::parseDateTime('2005-02-25 8:09 AM'), 1109347740 );

		TTDate::setTimeFormat('g:i A T');
		$this->assertEquals( TTDate::parseDateTime('2005-02-25 8:09 AM EST'), 1109336940 );

		TTDate::setTimeFormat('G:i');
		$this->assertEquals( TTDate::parseDateTime('2005-02-25 18:09'), 1109383740 );
		$this->assertEquals( TTDate::parseDateTime('2005-02-25 18:09 EST'), 1109372940 );
	}

	function test_getDayOfNextWeek() {
		Debug::text('Testing Date Format: Y-m-d', __FILE__, __LINE__, __METHOD__,10);

		TTDate::setDateFormat('Y-m-d');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::getDateOfNextDayOfWeek( strtotime('29-Dec-06'), strtotime('27-Dec-06') ), strtotime('03-Jan-07') );
		$this->assertEquals( TTDate::getDateOfNextDayOfWeek( strtotime('25-Dec-06'), strtotime('28-Dec-06') ), strtotime('28-Dec-06') );
		$this->assertEquals( TTDate::getDateOfNextDayOfWeek( strtotime('31-Dec-06'), strtotime('25-Dec-06') ), strtotime('01-Jan-07') );

	}

	function test_getDateOfNextDayOfMonth() {
		Debug::text('Testing Date Format: Y-m-d', __FILE__, __LINE__, __METHOD__,10);

		TTDate::setDateFormat('Y-m-d');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('01-Dec-06'), strtotime('02-Dec-06') ), strtotime('02-Dec-06') );
		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('14-Dec-06'), strtotime('23-Nov-06') ), strtotime('23-Dec-06') );
		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('14-Dec-06'), strtotime('13-Dec-06') ), strtotime('13-Jan-07') );
		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('14-Dec-06'), strtotime('14-Dec-06') ), strtotime('14-Dec-06') );
		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('12-Dec-06'), strtotime('01-Dec-04') ), strtotime('01-Jan-07') );

		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('12-Dec-06'), NULL, 1 ), strtotime('01-Jan-07') );
		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('12-Dec-06'), NULL, 12 ), strtotime('12-Dec-06') );
		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('12-Dec-06'), NULL, 31 ), strtotime('31-Dec-06') );

		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('01-Feb-07'), NULL, 31 ), strtotime('28-Feb-07') );
		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('01-Feb-08'), NULL, 29 ), strtotime('29-Feb-08') );
		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('01-Feb-08'), NULL, 31 ), strtotime('29-Feb-08') );

		//Anchor Epoch: 09-Apr-04 11:59 PM PDT Day Of Month Epoch:  Day Of Month: 24<br>
		$this->assertEquals( TTDate::getDateOfNextDayOfMonth( strtotime('09-Apr-04'), NULL, 24 ), strtotime('24-Apr-04') );
	}

	function test_parseEpoch() {
		Debug::text('Testing Date Parsing of EPOCH!', __FILE__, __LINE__, __METHOD__,10);

		TTDate::setDateFormat('m-d-y');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::parseDateTime(1162670400), (int)1162670400 );


		TTDate::setDateFormat('Y-m-d');
		TTDate::setTimeZone('PST');

		TTDate::setTimeFormat('g:i A');
		$this->assertEquals( TTDate::parseDateTime(1162670400), (int)1162670400 );
	}

	function test_roundTime() {
		//10 = Down
		//20 = Average
		//30 = Up

		//Test rounding down by 15minutes
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:06 AM'), (60*15), 10), strtotime('15-Apr-07 8:00 AM') );
		//Test rounding down by 5minutes
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:06 AM'), (60*5), 10), strtotime('15-Apr-07 8:05 AM') );
		//Test rounding down by 5minutes when no rounding should occur.
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:05 AM'), (60*5), 10), strtotime('15-Apr-07 8:05 AM') );

		//Test rounding down by 15minutes with 3minute grace.
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 4:58 PM'), (60*15), 10, (60*3) ), strtotime('15-Apr-07 5:00 PM') );
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 4:56 PM'), (60*15), 10, (60*3) ), strtotime('15-Apr-07 4:45 PM') );
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 5:11 PM'), (60*15), 10, (60*3) ), strtotime('15-Apr-07 5:00 PM') );
		//Test rounding down by 5minutes with 2minute grace
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 5:11 PM'), (60*5), 10, (60*2) ), strtotime('15-Apr-07 5:10 PM') );
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 5:07 PM'), (60*5), 10, (60*2) ), strtotime('15-Apr-07 5:05 PM') );


		//Test rounding avg by 15minutes
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:06 AM'), (60*15), 20), strtotime('15-Apr-07 8:00 AM') );
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:08 AM'), (60*15), 20), strtotime('15-Apr-07 8:15 AM') );
		//Test rounding avg by 5minutes
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:06 AM'), (60*5), 20), strtotime('15-Apr-07 8:05 AM') );
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:08 AM'), (60*5), 20), strtotime('15-Apr-07 8:10 AM') );
		//Test rounding avg by 5minutes when no rounding should occur.
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:05 AM'), (60*5), 20), strtotime('15-Apr-07 8:05 AM') );


		//Test rounding up by 15minutes
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:06 AM'), (60*15), 30), strtotime('15-Apr-07 8:15 AM') );
		//Test rounding up by 5minutes
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:06 AM'), (60*5), 30), strtotime('15-Apr-07 8:10 AM') );
		//Test rounding up by 5minutes when no rounding should occur.
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:05 AM'), (60*5), 30), strtotime('15-Apr-07 8:05 AM') );

		//Test rounding up by 15minutes with 3minute grace.
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:01 AM'), (60*15), 30, (60*3) ), strtotime('15-Apr-07 8:00 AM') );
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:04 AM'), (60*15), 30, (60*3) ), strtotime('15-Apr-07 8:15 AM') );
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:03 AM'), (60*15), 30, (60*3) ), strtotime('15-Apr-07 8:00 AM') );
		//Test rounding up by 5minutes with 2minute grace
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:03 AM'), (60*5), 30, (60*2) ), strtotime('15-Apr-07 8:05 AM') );
		$this->assertEquals( (int)TTDate::roundTime( strtotime('15-Apr-07 8:01 AM'), (60*5), 30, (60*2) ), strtotime('15-Apr-07 8:00 AM') );

	}

	function test_graceTime() {
		$this->assertEquals( (int)TTDate::graceTime( strtotime('15-Apr-07 7:58 AM'), (60*5), strtotime('15-Apr-07 8:00 AM') ), strtotime('15-Apr-07 8:00 AM') );
		$this->assertEquals( (int)TTDate::graceTime( strtotime('15-Apr-07 7:58:23 AM'), (60*5), strtotime('15-Apr-07 8:00 AM') ), strtotime('15-Apr-07 8:00 AM') );
	}
}
?>