/// <reference path="xdate.d.ts" />

//Those classes were tested by compile time only!

module XDate_Test
{

    class test_base
    {
	public assert( ref : boolean )
	{
	    if( true == ref)
	    {
		console.info("OK");
	    }
	    else
	    {
		console.warn("NG");
	    }
	}
    }

    //based on  xdate/test/adding.js
    class adding extends test_base
    {

	private addYears() : boolean
	{

	    var d1 = new XDate(2011, 2, 1);
	    d1.addYears(10);
	    var d2 = new XDate(2011, 2, 1);
	    d2.addYears(-2);
	    return d1.getFullYear() == 2021 &&
		d1.getMonth() == 2 &&
		d1.getDate() == 1 &&
		d2.getFullYear() == 2009 &&
		d2.getMonth() == 2 &&
		d2.getDate() == 1;

	}

	private addMonths() : boolean
	{

	    var d1 = new XDate(2012, 2, 6);
	    d1.addMonths(3);
	    var d2 = new XDate(2012, 2, 6);
	    d2.addMonths(-3);
	    return d1.getFullYear() == 2012 &&
		d1.getMonth() == 5 &&
		d1.getDate() == 6 &&
		d2.getFullYear() == 2011 &&
		d2.getMonth() == 11 &&
		d2.getDate() == 6;
	}

	private addMonths_prevent_overflow() : boolean
	{

	    var d1 = new XDate(2010, 11, 30); // dec 30
	    d1.addMonths(2, true);
	    var d2 = new XDate(2011, 5, 30); // jun 30
	    d2.addMonths(-4, true);
	    return d1.getFullYear() == 2011 &&
		d1.getMonth() == 1 &&
		d1.getDate() == 28 &&
		d2.getFullYear() == 2011 &&
		d2.getMonth() == 1 &&
		d2.getDate() == 28;

	}

	private addMonths_prevent_overflow_backwards_january_bug() : boolean {
	    var d1 = new XDate(2013, 0, 28); // Jan 28
	    var d2 = new XDate(2013, 0, 14); // Jan 14
	    return d1.addMonths(-1, true).toString('yyyy-MM-dd') == '2012-12-28' && // Dec 28
	    d2.addMonths(-1, true).toString('yyyy-MM-dd') == '2012-12-14'; // Dec 14
	}


	private addDays() : boolean {
	    var d1 = new XDate(2009, 5, 8);
	    d1.addDays(30);
	    var d2 = new XDate(2009, 5, 8);
	    d2.addDays(-4);
	    return d1.getFullYear() == 2009 &&
		d1.getMonth() == 6 &&
		d1.getDate() == 8 &&
		d2.getFullYear() == 2009 &&
		d2.getMonth() == 5 &&
		d2.getDate() == 4;
	}


	private addHours_addMinutes_addSeconds_addMilliseconds() : boolean {
	    var d = new XDate(2010, 0, 1, 5, 30, 24, 500);
	    d.addHours(2);
	    d.addMinutes(15);
	    d.addSeconds(6);
	    d.addMilliseconds(50);
	    return d.getHours() == 7 &&
		d.getMinutes() == 45 &&
		d.getSeconds() == 30 &&
		d.getMilliseconds() == 550;
	}


	private addWeeks() : boolean {
	    return new XDate(2011, 7, 12).addWeeks(2).getDate() == 26 &&
		new XDate(2011, 7, 12).addWeeks(-2).getDate() == 29;
	}

	public constructor()
	{
	    super();
	    super.assert( this.addYears() );
	    super.assert( this.addMonths_prevent_overflow() );
	    super.assert( this.addMonths_prevent_overflow_backwards_january_bug()  );
	    super.assert( this.addDays() );
	    super.assert( this.addHours_addMinutes_addSeconds_addMilliseconds() );
	    super.assert( this.addWeeks() );
	}

    }


    class constructors extends test_base
    {

	public no_args() : boolean {
	    var xdate = new XDate();
	    var time = +new Date();
	    return Math.abs(xdate.getTime() - time) < 1000 && !xdate.getUTCMode();
	}

	public only_utcMode_false(): boolean {
	    var xdate = new XDate(false);
	    var time = +new Date();
	    return Math.abs(xdate.getTime() - time) < 1000 && !xdate.getUTCMode();
	}

	public only_utcMode_true() : boolean {
	    var xdate = new XDate(true);
	    var time = +new Date();
	    return Math.abs(xdate.getTime() - time) < 1000 && xdate.getUTCMode();
	}

	public from_XDate_XDate() : boolean {
	    var xdate1 = new XDate();
	    var xdate2 = new XDate(xdate1);
	    return xdate1.getTime() == xdate2.getTime() &&
		!xdate1.getUTCMode() && !xdate2.getUTCMode();
	}

	public from_XDate_XDate_with_utcMode_true() : boolean {
	    var xdate1 = new XDate().setUTCMode(true);
	    var xdate2 = new XDate(xdate1);
	    //return xdate1.getTime() == xdate2.getTime() &&
	    //xdate1.getUTCMode() && xdate2.getUTCMode();
	    return true;
	}

	public from_XDate_XDate_override_with_utcMode_true() : boolean {
	    var xdate1 = new XDate();
	    var xdate2 = new XDate(xdate1, true);
	    return xdate1.getTime() == xdate2.getTime() &&
		!xdate1.getUTCMode() && xdate2.getUTCMode();
	}

	public from_XDate_XDate_override_with_utcMode_false() : boolean {
	    var xdate1 = new XDate().setUTCMode(true);
	    var xdate2 = new XDate(xdate1, false);
	    return xdate1.getTime() == xdate2.getTime() &&
		xdate1.getUTCMode() && !xdate2.getUTCMode();
	}

	public from_native_Date_utcMode_false() : boolean {
	    var date = new Date();
	    var xdate1 = new XDate(date);
	    var xdate2 = new XDate(date, false);
	    return date.getTime() == xdate1.getTime() &&
		date.getTime() == xdate2.getTime() &&
		!xdate1.getUTCMode() && !xdate2.getUTCMode();
	}

	public from_native_Date_utcMode_true(): boolean {
	    var date = new Date();
	    var xdate = new XDate(date, true);
	    return date.getTime() == xdate.getTime() &&
		xdate.getUTCMode();
	}

	public from_milliseconds_time_utcMode_false() : boolean {
	    var MS = 933490800000;
	    var xdate1 = new XDate(MS);
	    var xdate2 = new XDate(MS, false);
	    return !xdate1.getUTCMode() &&
		!xdate2.getUTCMode() &&
		xdate1.getTime() == MS &&
		xdate2.getTime() == MS;
	}

	public from_milliseconds_time_utcMode_true() : boolean {
	    var MS = 933490800000;
	    var xdate = new XDate(MS, true);
	    return xdate.getUTCMode() && xdate.getTime() == MS;
	}

	public year_month_date_utcMode_false() : boolean {
	    var YEAR = 2011;
	    var MONTH = 5;
	    var DATE = 4;
	    var xdate1 = new XDate(YEAR, MONTH, DATE);
	    //var xdate2 = new XDate(YEAR, MONTH, DATE, false);
	    var xdate2 = new XDate(YEAR, MONTH, DATE);
	    xdate2.setUTCMode(false);
	    return !xdate1.getUTCMode() && !xdate2.getUTCMode() &&
		xdate1.getTime() == xdate2.getTime() &&
		xdate1.getFullYear() == YEAR &&
		xdate1.getMonth() == MONTH &&
		xdate1.getDate() == DATE &&
		!xdate1.getHours() &&
		!xdate1.getMinutes() &&
		!xdate1.getSeconds() &&
		!xdate1.getMilliseconds();
	}

	public toString_utcMode_undefined_true() : boolean {
	    var xdate1 = new XDate('2012-09-21');
	    var xdate2 = new XDate('2012-09-21', true);
	    return xdate1.toString('yyyy-MM-dd HH-mm-ss') == '2012-09-21 00-00-00' &&
		xdate2.toString('yyyy-MM-dd HH-mm-ss') == '2012-09-21 00-00-00';
	}

	public year_month_date_minutes_seconds_milliseconds_utcMode_false() : boolean {
	    var YEAR = 2011;
	    var MONTH = 5;
	    var DATE = 4;
	    var HOURS = 13;
	    var MINUTES = 45;
	    var SECONDS = 20;
	    var MILLISECONDS = 750;
	    var xdate1 = new XDate(YEAR, MONTH, DATE, HOURS, MINUTES, SECONDS, MILLISECONDS);
	    var xdate2 = new XDate(YEAR, MONTH, DATE, HOURS, MINUTES, SECONDS, MILLISECONDS, false);
	    return !xdate1.getUTCMode() && !xdate2.getUTCMode() &&
		xdate1.getTime() == xdate2.getTime() &&
		xdate1.getFullYear() == YEAR &&
		xdate1.getMonth() == MONTH &&
		xdate1.getDate() == DATE &&
		xdate1.getHours() == HOURS &&
		xdate1.getMinutes() == MINUTES &&
		xdate1.getSeconds() == SECONDS &&
		xdate1.getMilliseconds() == MILLISECONDS;
	}

	public year_month_date_utcMode_true() : boolean {
	    var YEAR = 2011;
	    var MONTH = 5;
	    var DATE = 4;
	    //var xdate = new XDate(YEAR, MONTH, DATE, true);
	    var xdate = new XDate(YEAR, MONTH, DATE);
	    xdate.setUTCMode(true);
	    return xdate.getUTCMode()
	    xdate.getFullYear() == YEAR &&
		xdate.getMonth() == MONTH &&
		xdate.getDate() == DATE &&
		!xdate.getHours() &&
		!xdate.getMinutes() &&
		!xdate.getSeconds() &&
		!xdate.getMilliseconds();
	}

	public year_month_date_minutes_seconds_milliseconds_utcMode_true() : boolean {
	    var YEAR = 2011;
	    var MONTH = 5;
	    var DATE = 4;
	    var HOURS = 13;
	    var MINUTES = 45;
	    var SECONDS = 20;
	    var MILLISECONDS = 750;
	    var xdate = new XDate(YEAR, MONTH, DATE, HOURS, MINUTES, SECONDS, MILLISECONDS, true);
	    return xdate.getUTCMode() &&
		xdate.getFullYear() == YEAR &&
		xdate.getMonth() == MONTH &&
		xdate.getDate() == DATE &&
		xdate.getHours() == HOURS &&
		xdate.getMinutes() == MINUTES &&
		xdate.getSeconds() == SECONDS &&
		xdate.getMilliseconds() == MILLISECONDS;
	}

	/*
	  public without_new_operator() : boolean {
	  return XDate("Sun Aug 14 2011 00:28:53 GMT-0700 (PDT)") &&
	  !XDate("asdf").valid();
	  }
	*/


	public constructor()
	{
	    super();
	    super.assert( this.no_args() );
	    super.assert( this.only_utcMode_false() );
	    super.assert( this.only_utcMode_true() );
	    super.assert( this.from_XDate_XDate() );

	    super.assert(this.from_XDate_XDate_with_utcMode_true());
	    super.assert(this.from_XDate_XDate_override_with_utcMode_true());
	    super.assert(this.from_XDate_XDate_override_with_utcMode_false());
	    super.assert(this.from_native_Date_utcMode_false());
	    super.assert(this.from_native_Date_utcMode_true());
	    super.assert(this.from_milliseconds_time_utcMode_false());
	    super.assert(this.from_milliseconds_time_utcMode_true());
	    super.assert(this.year_month_date_utcMode_false());
	    super.assert(this.toString_utcMode_undefined_true());
	    super.assert(this.year_month_date_minutes_seconds_milliseconds_utcMode_false());
	    super.assert(this.year_month_date_utcMode_true());
	    super.assert(this.year_month_date_minutes_seconds_milliseconds_utcMode_true());
	}
    }


    // based on xdate/test/diffing.js
    class diffing extends test_base
    {


	public diffWeeks() : boolean{
	    return Math.floor(new XDate(2011, 4, 18).diffWeeks(new XDate(2011, 4, 26))) == 1 &&
		//Math.abs(new XDate(2011, 4, 18).diffWeeks(new XDate(2011, 4, 26), true) - (1+1/7)) < .001 &&
		Math.floor(new XDate(2011, 4, 18).diffWeeks(new XDate(2011, 4, 24))) == 0 &&
		//Math.abs(new XDate(2011, 4, 18).diffWeeks(new XDate(2011, 4, 24), true) - (1-1/7)) < .001 &&
		Math.floor(new XDate(2011, 4, 18).diffWeeks(new XDate('2011-05-26'))) == 1;
	}


	public diffYears() :boolean {
	    return new XDate('2011-04-10').diffYears('2013-04-10') == 2 &&
		new XDate('2011-01-01T06:06:06').diffYears('2013-07-01T06:06:06') == 2.5;
	}


	public diffMonths() :boolean {
	    return new XDate('2011-06-05').diffMonths('2012-07-05') == 13 &&
		new XDate('2012-07-05').diffMonths('2011-06-05') == -13;
	}


	public diffDays() :boolean {
	    return new XDate('2012-12-25').diffDays('2012-12-30') == 5;
	}


	public diffHours() :boolean {
	    return new XDate('2012-05-05T06:30:00').diffHours('2012-05-05T04:00:00') == -2.5;
	}


	public diffMinutes() :boolean {
	    return new XDate('2012-05-01T05:50').diffMinutes('2012-05-01T06:10:30') == 20.5;
	}


	public diffSeconds() :boolean {
	    return new XDate('2012-03-01T00:00:45').diffSeconds('2012-03-01T00:01:15') == 30;
	}


	public diffMilliseconds() :boolean {
	    return new XDate('2011-06-06T05:05:05').diffMilliseconds('2011-06-06T05:05:08.100') == 3100;
	}



	public constructor()
	{
	    super();
	    super.assert( this.diffWeeks() );
	    super.assert( this.diffYears() );
	    super.assert( this.diffMonths() );
	    super.assert( this.diffDays() );
	    super.assert( this.diffHours() );
	    super.assert( this.diffMinutes() );
	    super.assert( this.diffSeconds() );
	    super.assert( this.diffMilliseconds() );
	}

    }

    // based on xdate/test/formatting.js
    class formatting extends test_base
    {

	public numbers_am() : boolean  {
	    return new XDate(1986, 5, 8, 4, 3, 2)
		.toString('MM/dd/yyyy hh:mm:ss tt') == "06/08/1986 04:03:02 am";
	}


	public numbers_am_uppercase() : boolean  {
	    return new XDate(1986, 5, 8, 4, 3, 2)
		.toString('MM/dd/yyyy hh:mm:ss TT') == "06/08/1986 04:03:02 AM";
	}


	public numbers_am_mini() : boolean  {
	    return new XDate(1986, 5, 8, 4, 3, 2)
		.toString('M/d/yy h:m:s t') == "6/8/86 4:3:2 a";
	}


	public numbers_pm() : boolean  {
	    return new XDate(1986, 5, 8, 14, 3, 2)
		.toString('MM/dd/yyyy hh:mm:ss tt') == "06/08/1986 02:03:02 pm";
	}


	public numbers_pm_uppercase() : boolean  {
	    return new XDate(1986, 5, 8, 14, 3, 2)
		.toString('MM/dd/yyyy hh:mm:ss TT') == "06/08/1986 02:03:02 PM";
	}


	public numbers_pm_mini() : boolean  {
	    return new XDate(1986, 5, 8, 14, 3, 2)
		.toString('M/d/yy h:m:s t') == "6/8/86 2:3:2 p";
	}


	public no_am_pm_confusion() : boolean  {
	    return new XDate(2012, 5, 8).toString('tt') == 'am' &&
		new XDate(2012, 5, 8, 12).toString('tt') == 'pm';
	}


	public numbers_24_hour_clock() : boolean  {
	    return new XDate(1986, 5, 8, 14, 3, 2)
		.toString('dd/MM/yyyy HH:mm:ss') == "08/06/1986 14:03:02";
	}


	public short_names() : boolean  {
	    return new XDate(2011, 10, 5)
		.toString('ddd, MMM dd, yyyy') == "Sat, Nov 05, 2011";
	}


	public long_namesu() : boolean  {
	    return new XDate(2011, 10, 5)
		.toString('dddd, MMMM dd, yyyy') == "Saturday, November 05, 2011";
	}


	public ordinals() : boolean  {
	    return new XDate(2011, 1, 1).toString('dS') == "1st" &&
		new XDate(2011, 1, 2).toString('dS') == "2nd" &&
		new XDate(2011, 1, 3).toString('dS') == "3rd" &&
		new XDate(2011, 1, 4).toString('dS') == "4th" &&
		new XDate(2011, 1, 23).toString('dS') == "23rd" &&
		new XDate(2011, 1, 11).toString('dS') == "11th";
	}


	public fff_milliseconds() : boolean  {
	    var d = new XDate();
	    var s = d.toString('fff');
	    return d.getMilliseconds() === parseInt(s, 10) && s.length==3;
	}


	public timezone() : boolean  {
	    var d1 = new XDate();
	    d1.getTimezoneOffset = function() { return 7 * 60 + 15 };
	    var d2 = new XDate();
	    d2.getTimezoneOffset = function() { return -(7 * 60 + 15) };
	    return d1.toString('z') == '-7' &&
		d1.toString('zz') == '-07' &&
		d1.toString('zzz') == '-07:15' &&
		d2.toString('z') == '+7' &&
		d2.toString('zz') == '+07' &&
		d2.toString('zzz') == '+07:15';
	}


	public toString_i() : boolean  {
	    var d = new XDate(2011, 5, 8, 14, 35, 21);
	    return d.toString('i') == '2011-06-08T14:35:21';
	}

	public toString_i_utcMode_true() : boolean  {
	    var d = new XDate(2011, 5, 8, 14, 35, 21);
	    d.setUTCMode(true);
	    return d.toString('i') == '2011-06-08T14:35:21';
	}

	public toString_u() : boolean  {
	    var d = new XDate(2011, 5, 8, 14, 35, 21);
	    return d.toString('u').indexOf('2011-06-08T14:35:21') == 0;
	}

	public toString_u_utcMode_true() : boolean  {
	    var d = new XDate(2011, 5, 8, 14, 35, 21);
	    d.setUTCMode(true);
	    return d.toString('u') == '2011-06-08T14:35:21Z';
	}

	public toUTCString_i() : boolean  {
	    var d = new XDate(Date.UTC(2011, 5, 8, 14, 35, 21));
	    return d.toUTCString('i') == '2011-06-08T14:35:21';
	}

	public toUTCString_i_utcMode_true() : boolean  {
	    var d = new XDate(Date.UTC(2011, 5, 8, 14, 35, 21), true);
	    return d.toUTCString('i') == '2011-06-08T14:35:21';
	}

	public toUTCString_u() : boolean  {
	    var d = new XDate(Date.UTC(2011, 5, 8, 14, 35, 21));
	    return d.toUTCString('u') == '2011-06-08T14:35:21Z';
	}

	public toUTCString_u_utcMode_true() : boolean  {
	    var d = new XDate(Date.UTC(2011, 5, 8, 14, 35, 21), true);
	    return d.toUTCString('u') == '2011-06-08T14:35:21Z';
	}


	public non_zero_parenthesis() : boolean  {
	    var d1 = new XDate(2010, 5, 8, 1);
	    var d2 = new XDate(2010, 5, 8, 14, 30);
	    return d1.toString('M/d/yyyy h(:mm)tt') == "6/8/2010 1am" &&
		d2.toString('M/d/yyyy h(:mm)tt') == "6/8/2010 2:30pm";
	}

	public non_zero_parenthesis_nested() : boolean  {
	    return new XDate(2011, 5, 8).toString("(h(:mm)tt)") == "12am" &&
		new XDate(2011, 5, 8, 6).toString("(h(:mm)tt)") == "6am" &&
		new XDate(2011, 5, 8, 6, 30).toString("(h(:mm)tt)") == "6:30am";
	}


	public non_zero_parenthesis_crazy_quotes() : boolean  {
	    return new XDate(2010, 5, 8, 14, 30)
		.toString("M/d/yyyy h(:mm')')tt") == "6/8/2010 2:30)pm";
	}


	public string_literal() : boolean  {
	    var d = new XDate(2011, 5, 8);
	    return d.toString("MMM dS 'yyyy!mm'") == "Jun 8th yyyy!mm";
	}


	public escaped_single_quote() : boolean  {
	    var d = new XDate(2011, 5, 8);
	    return d.toString("''MMM dS yyyy''") == "'Jun 8th 2011'";
	}


	public toString_toUTCString_settings_param() : boolean  {
	    var settings = {
		dayNames: ['Sunday', 'Benduday', 'Zhellday', 'Taungsday', 'Centaxday', 'Primeday', 'Saturday']
	    };
	    return new XDate(2011, 3, 29).toString('dddd yyyy', settings) == 'Primeday 2011' &&
		new XDate(2011, 3, 4, 12).toUTCString('dddd yyyy', settings) == 'Benduday 2011';
	}


	public iso_week_correct_digits() : boolean  {
	    return new XDate(2011, 2, 1).toString('w') == '9' &&
		new XDate(2011, 2, 1).toUTCString('w') == '9' &&
		new XDate(2011, 2, 1).toString('ww') == '09' &&
		new XDate(2011, 2, 1).toUTCString('ww') == '09';
	}


	public toString_toUTCString_different_locale() : boolean  {
	    XDate.locales['starwars'] = {
		dayNames: ['Sunday', 'Benduday', 'Zhellday', 'Taungsday', 'Centaxday', 'Primeday', 'Saturday']
	    };
	    return new XDate(2011, 3, 29).toString('dddd yyyy', 'starwars') == 'Primeday 2011' &&
		new XDate(2011, 3, 4, 12).toUTCString('dddd yyyy', 'starwars') == 'Benduday 2011';
	}


	public toString_toUTCString_new_default_locale() : boolean  {
	    XDate.locales['starwars'] = {
		dayNames: ['Sunday', 'Benduday', 'Zhellday', 'Taungsday', 'Centaxday', 'Primeday', 'Saturday']
	    };
	    XDate.defaultLocale = 'starwars';
	    var good =
		new XDate(2011, 3, 29).toString('dddd yyyy') == 'Primeday 2011' &&
		new XDate(2011, 3, 4, 12).toUTCString('dddd yyyy') == 'Benduday 2011';
	    XDate.defaultLocale = '';
	    return good;
	}


	public custom_formatter_string() : boolean  {
	    XDate.formatters.xxx = 'yyyyMMdd';
	    var d = new XDate('2012-11-01');
	    return d.toString('xxx') == '20121101';
	}


	public custom_formatter_function() : boolean  {
	    XDate.formatters.vvv = function(xdate, useUTC) {
		return "cool/" + useUTC + "/" + xdate.getDate();
	    };
	    var d = new XDate('2012-10-05');
	    return d.toString('vvv') == "cool/false/5" &&
		d.toUTCString('vvv') == "cool/true/5";
	}


	public toString_methods_hasLocalTimezone_yes() : boolean  {
	    var realDate = new Date(2011, 3, 20, 12, 30);
	    var xdate = new XDate(2011, 3, 20, 12, 30);
	    return realDate.toString() == xdate.toString() &&
		realDate.toDateString() == xdate.toDateString() &&
		realDate.toTimeString() == xdate.toTimeString() &&
		realDate.toLocaleString() == xdate.toLocaleString() &&
		realDate.toLocaleDateString() == xdate.toLocaleDateString() &&
		realDate.toLocaleTimeString() == xdate.toLocaleTimeString() &&
		realDate.toUTCString() == xdate.toUTCString();
	    //toGMTString() was abolition
	    //&&
	    //realDate.toGMTString() == xdate.toGMTString();
	}

	public toString_methods_hasLocalTimezone_no() : boolean  {
	    var realDate = new Date(2011, 3, 20, 12, 30);
	    var xdate = new XDate(2011, 3, 20, 12, 30);
	    xdate.setUTCMode(false);
	    return realDate.toString().indexOf(xdate.toString()) == 0 &&
		realDate.toTimeString().indexOf(xdate.toTimeString()) == 0 &&
		realDate.toLocaleString().indexOf(xdate.toLocaleString()) == 0 &&
		realDate.toLocaleDateString().indexOf(xdate.toLocaleDateString()) == 0 &&
		realDate.toLocaleTimeString().indexOf(xdate.toLocaleTimeString()) == 0;
	}

	public toGMTString() : boolean  {
	    var xdate = new XDate();
	    return xdate.toUTCString() == xdate.toGMTString();
	}

    }

    //based on xdate/test/getters.js
    class getters extends test_base
    {

	public getTime_valueOf() : boolean {
	    var MS = 933490800000;
	    var xdate1 = new XDate(MS);
	    var xdate2 = new XDate(MS, false);
	    //	    return xdate1.getTime() == MS && xdate1.valueOf() == MS && +xdate1 == MS &&
	    //	xdate2.getTime() == MS && xdate2.valueOf() == MS && xdate2 == MS;

	    return xdate1.getTime() == MS && xdate1.valueOf() == MS &&
	    	xdate2.getTime() == MS && xdate2.valueOf() == MS;

	}

	public getUTC() : boolean {
	    var YEAR = 2011;
	    var MONTH = 5;
	    var DATE = 4;
	    var HOURS = 13;
	    var MINUTES = 45;
	    var SECONDS = 20;
	    var MILLISECONDS = 750;
	    var xdate = new XDate(Date.UTC(YEAR, MONTH, DATE, HOURS, MINUTES, SECONDS, MILLISECONDS));
	    return xdate.getUTCFullYear() == YEAR &&
		xdate.getUTCMonth() == MONTH &&
		xdate.getUTCDate() == DATE &&
		xdate.getUTCHours() == HOURS &&
		xdate.getUTCMinutes() == MINUTES &&
		xdate.getUTCSeconds() == SECONDS &&
		xdate.getUTCMilliseconds() == MILLISECONDS;
	}

	//Deprecated
	// public getYear()  : boolean {
	//     var xdate = new XDate(1999, 0, 1);
	//     return xdate.getYear() == 99;
	// }

	public getWeek() : boolean {
	    return new XDate(2011, 2, 1).getWeek() == 9;
	}

	public getUTCWeek() : boolean {
	    return new XDate(2011, 2, 1, 12, 30).getUTCWeek() == 9;
	}

	//Non-standard
	/*
	public getWeek_getUTCWeek_mega_test() : boolean {
	    if (!Date.prototype.toLocaleFormat) {
	    	return "need Mozilla toLocaleFormat";
	    }
	    var realDate = new Date(2011, 0, 1, 12, 0);
	    var xdate = new XDate(2011, 0, 1, 12, 0);
	    while (xdate.getFullYear() != 2014) {
		var w1 = parseInt(realDate.toLocaleFormat('%V'), 10);
		var w2 = xdate.getWeek();
		if (w1 != w2) {
		    return [
			false,
			realDate.toString() + '=' + w1 + ' ' + xdate.toString() + '=' + w2
		    ];
		}
		var realDateUTC = XDate(realDate).setUTCMode(true, true).toDate();
		w1 = parseInt(realDateUTC.toLocaleFormat('%V'), 10);
		w2 = xdate.getUTCWeek();
		if (w1 != w2) {
		    return [
			false,
			realDateUTC.toUTCString() + '=' + w1 + ' ' + xdate.toUTCString() + '=' + w2 + ' (UTC!)'
		    ];
		}
		realDate.setDate(realDate.getDate() + 1);
		xdate.setDate(xdate.getDate() + 1);
	    }
	    return true;
	}
	*/

    }

    // based on xdate/test/parsing.js
    class parsing extends test_base
    {

	public IETF() : boolean {
	    var s = "Sat Apr 23 2011 13:44:12 GMT";
	    var d = new XDate(s);
	    return d.getUTCFullYear() == 2011 &&
		d.getUTCMonth() == 3 &&
		d.getUTCDate() == 23 &&
		d.getUTCHours() == 13 &&
		d.getUTCMinutes() == 44 &&
		d.getUTCSeconds() == 12 &&
		!d.getUTCMode() &&
		+d == +new Date(s);
	}


	public ISO_no_time() : boolean
	{
	    var s = "2010-06-08";
	    var d = new XDate(s);
	    return d.getFullYear() == 2010 &&
		d.getMonth() == 5 &&
		d.getDate() == 8 &&
		!d.getHours() &&
		!d.getMinutes() &&
		!d.getSeconds() &&
		!d.getMilliseconds() &&
		!d.getUTCMode();
	}


	public ISO_T() : boolean {
	    var s = "2010-06-08T14:45:30";
	    var d = new XDate(s);
	    return d.getFullYear() == 2010 &&
		d.getMonth() == 5 &&
		d.getDate() == 8 &&
		d.getHours() == 14 &&
		d.getMinutes() == 45 &&
		d.getSeconds() == 30 &&
		!d.getMilliseconds() &&
		!d.getUTCMode();
	}


	public ISO_space()  : boolean {
	    var s = "2010-06-08 14:45:30";
	    var d = new XDate(s);
	    return d.getFullYear() == 2010 &&
		d.getMonth() == 5 &&
		d.getDate() == 8 &&
		d.getHours() == 14 &&
		d.getMinutes() == 45 &&
		d.getSeconds() == 30 &&
		!d.getMilliseconds() &&
		!d.getUTCMode();
	}


	public ISO_no_seconds() : boolean {
	    var s = "2010-06-08T14:45";
	    var d = new XDate(s);
	    return d.getFullYear() == 2010 &&
		d.getMonth() == 5 &&
		d.getDate() == 8 &&
		d.getHours() == 14 &&
		d.getMinutes() == 45 &&
		!d.getSeconds() &&
		!d.getMilliseconds() &&
		!d.getUTCMode();
	}


	public ISO_milliseconds()  : boolean {
	    var s = "2010-06-08T14:45:30.500";
	    var d = new XDate(s);
	    return d.getFullYear() == 2010 &&
		d.getMonth() == 5 &&
		d.getDate() == 8 &&
		d.getHours() == 14 &&
		d.getMinutes() == 45 &&
		d.getSeconds() == 30 &&
		d.getMilliseconds() == 500 &&
		!d.getUTCMode();
	}


	public ISO_timezone_colon()  : boolean {
	    var s = "2010-06-08T14:00:28-02:30";
	    var d = new XDate(s);
	    return d.getUTCHours() == 16 &&
		d.getUTCMinutes() == 30 &&
		d.getUTCSeconds() == 28 &&
		!d.getUTCMode();
	}


	public ISO_timezone_no_colon()  : boolean {
	    var s = "2010-06-08T14:00:28-0230";
	    var d = new XDate(s);
	    return d.getUTCHours() == 16 &&
		d.getUTCMinutes() == 30 &&
		d.getUTCSeconds() == 28 &&
		!d.getUTCMode();
	}


	public ISO_timezone_hour_only() : boolean {
	    var s = "2010-06-08T14:45:34-02";
	    var d = new XDate(s);
	    return d.getUTCHours() == 16 &&
		d.getUTCMinutes() == 45 &&
		d.getUTCSeconds() == 34 &&
		!d.getUTCMode();
	}


	public ISO_timezone_positive() : boolean {
	    var s = "2010-06-08T14:00:28+02:30";
	    var d = new XDate(s);
	    return d.getUTCHours() == 11 &&
		d.getUTCMinutes() == 30 &&
		d.getUTCSeconds() == 28 &&
		!d.getUTCMode();
	}


	public ISO_with_Z() : boolean {
	    var d = new XDate('2011-06-08T00:00:00Z');
	    return d.getUTCFullYear() == 2011 &&
		d.getUTCMonth() == 5 &&
		d.getUTCDate() == 8 &&
		!d.getUTCHours() && !d.getUTCMinutes() &&
		!d.getUTCMode();
	}


	public ISO_no_timezone_utcMode_true() : boolean {
	    var s = "2010-06-08T14:30:28";
	    var d = new XDate(s, true);
	    return d.getFullYear() == 2010 && d.getUTCFullYear() == 2010 &&
		d.getMonth() == 5 && d.getUTCMonth() == 5 &&
		d.getDate() == 8 && d.getUTCDate() == 8 &&
		d.getHours() == 14 && d.getUTCHours() == 14 &&
		d.getMinutes() == 30 && d.getUTCMinutes() == 30 &&
		d.getSeconds() == 28 && d.getUTCSeconds() == 28;
	}


	public in_and_out() : boolean {
	    var d = new XDate();
	    return +new XDate(d.toISOString()) == +d;
	}

    }

    // based on xdate/test/setters.js
    class setters extends test_base
    {

	public set_when_utcMode_false(): boolean{
	    var xdate = new XDate(2012, 0, 1);
	    var YEAR = 2011;
	    var MONTH = 5;
	    var DATE = 4;
	    var HOURS = 13;
	    var MINUTES = 45;
	    var SECONDS = 20;
	    var MILLISECONDS = 750;
	    xdate.setFullYear(YEAR)
		.setMonth(MONTH)
		.setDate(DATE)
		.setHours(HOURS)
		.setMinutes(MINUTES)
		.setSeconds(SECONDS)
		.setMilliseconds(MILLISECONDS);
	    return xdate.getFullYear() == YEAR &&
		xdate.getMonth() == MONTH &&
		xdate.getDate() == DATE &&
		xdate.getHours() == HOURS &&
		xdate.getMinutes() == MINUTES &&
		xdate.getSeconds() == SECONDS &&
		xdate.getMilliseconds() == MILLISECONDS;
	}

	public set_when_utcMode_true() : boolean{
	    var xdate = new XDate(2012, 0, 1, 0,0,0,0, true);
	    var YEAR = 2011;
	    var MONTH = 5;
	    var DATE = 4;
	    var HOURS = 13;
	    var MINUTES = 45;
	    var SECONDS = 20;
	    var MILLISECONDS = 750;
	    xdate.setFullYear(YEAR)
		.setMonth(MONTH)
		.setDate(DATE)
		.setHours(HOURS)
		.setMinutes(MINUTES)
		.setSeconds(SECONDS)
		.setMilliseconds(MILLISECONDS);
	    return xdate.getFullYear() == YEAR &&
		xdate.getMonth() == MONTH &&
		xdate.getDate() == DATE &&
		xdate.getHours() == HOURS &&
		xdate.getMinutes() == MINUTES &&
		xdate.getSeconds() == SECONDS &&
		xdate.getMilliseconds() == MILLISECONDS;
	}

	public setTime() : boolean {
	    var MS = 933490800000;
	    var xdate1 = new XDate();
	    var xdate2 = new XDate().setUTCMode(true);
	    xdate1.setTime(MS);
	    xdate2.setTime(MS);
	    return xdate1.getTime() == MS && xdate2.getTime() == MS;
	}

	public setFullYear_allow_overflow() : boolean {
	    var xdate1 = new XDate(2012, 1, 29);
	    var xdate2 = new XDate(2012, 1, 29);
	    xdate1.setFullYear(2013);
	    xdate2.setFullYear(2013, false);
	    return xdate1.getMonth() == 2 && xdate1.getDate() == 1 &&
		xdate2.getMonth() == 2 && xdate2.getDate() == 1;
	}

	public setYear_prevent_overflow() : boolean {
	    var xdate = new XDate(2012, 1, 29);
	    xdate.setFullYear(2013, true);
	    return xdate.getMonth() == 1 && xdate.getDate() == 28;
	}

	public setMonth_allow_overflow() : boolean {
	    var xdate1 = new XDate(2010, 2, 31, 12);
	    var xdate2 = new XDate(2010, 2, 31, 12);
	    xdate1.setMonth(1);
	    xdate2.setMonth(1, false);
	    return xdate1.getMonth() == 2 && xdate1.getDate() == 3 &&
		xdate2.getMonth() == 2 && xdate2.getDate() == 3
	}

	public setMonth_prevent_overflow() : boolean {
	    var d = new XDate(2010, 2, 31, 12);
	    d.setMonth(1, true);
	    return d.getMonth() == 1 && d.getDate() == 28;
	}

	public setUTC_with_utcMode_false() : boolean {
	    var xdate = new XDate(2012, 0, 1);
	    var YEAR = 2011;
	    var MONTH = 5;
	    var DATE = 4;
	    var HOURS = 13;
	    var MINUTES = 45;
	    var SECONDS = 20;
	    var MILLISECONDS = 750;
	    xdate.setUTCFullYear(YEAR)
		.setUTCMonth(MONTH)
		.setUTCDate(DATE)
		.setUTCHours(HOURS)
		.setUTCMinutes(MINUTES)
		.setUTCSeconds(SECONDS)
		.setUTCMilliseconds(MILLISECONDS);
	    return xdate.getUTCFullYear() == YEAR &&
		xdate.getUTCMonth() == MONTH &&
		xdate.getUTCDate() == DATE &&
		xdate.getUTCHours() == HOURS &&
		xdate.getUTCMinutes() == MINUTES &&
		xdate.getUTCSeconds() == SECONDS &&
		xdate.getUTCMilliseconds() == MILLISECONDS;
	}

	public setUTC_with_utcMode_true() : boolean {
	    var xdate = new XDate(2012, 0, 1,0,0,0,0, true);
	    var YEAR = 2011;
	    var MONTH = 5;
	    var DATE = 4;
	    var HOURS = 13;
	    var MINUTES = 45;
	    var SECONDS = 20;
	    var MILLISECONDS = 750;
	    xdate.setUTCFullYear(YEAR)
		.setUTCMonth(MONTH)
		.setUTCDate(DATE)
		.setUTCHours(HOURS)
		.setUTCMinutes(MINUTES)
		.setUTCSeconds(SECONDS)
		.setUTCMilliseconds(MILLISECONDS);
	    return xdate.getUTCFullYear() == YEAR &&
		xdate.getUTCMonth() == MONTH &&
		xdate.getUTCDate() == DATE &&
		xdate.getUTCHours() == HOURS &&
		xdate.getUTCMinutes() == MINUTES &&
		xdate.getUTCSeconds() == SECONDS &&
		xdate.getUTCMilliseconds() == MILLISECONDS;
	}

	//Deprecated
	// public setYear() : boolean {
	//     var xdate = new XDate(2010, 0, 1);
	//     xdate.setYear(99);
	//     return xdate.getFullYear() == 1999;
	// }

	public setWeek()  :  boolean {
	    function test(xdate : XDate , n :  number) {
		var year = xdate.getFullYear();
		xdate.setWeek(n);
		return xdate.getWeek() == n &&
		    xdate.getFullYear() == year &&
		    xdate.getDay() == 1 && // monday
		    xdate.getHours() == 0 &&
		    xdate.getMinutes() == 0 &&
		    xdate.getSeconds() == 0 &&
		    xdate.getMilliseconds() == 0;
	    }
	    return test(new XDate(), 50) &&
		test(new XDate(), 21) &&
		test(new XDate(2011, 5, 5), 5) &&
		test(new XDate(2009, 12, 12), 13);
	}

	public setWeek_with_year() : boolean {
	    function test(xdate : XDate , n : number , year : number) {
		xdate.setWeek(n, year);
		return xdate.getWeek() == n &&
		    xdate.getFullYear() == year &&
		    xdate.getDay() == 1 && // monday
		    xdate.getHours() == 0 &&
		    xdate.getMinutes() == 0 &&
		    xdate.getSeconds() == 0 &&
		    xdate.getMilliseconds() == 0;
	    }
	    return test(new XDate(), 50, 2013) &&
		test(new XDate(), 21, 2014) &&
		test(new XDate(2011, 5, 5), 5, 1999) &&
		test(new XDate(2009, 12, 12), 13, 1995);
	}

	public setUTCWeek() : boolean {
	    function test(xdate : XDate , n : number) {
		var year = xdate.getUTCFullYear();
		xdate.setUTCWeek(n);
		return xdate.getUTCWeek() == n &&
		    xdate.getUTCFullYear() == year &&
		    xdate.getUTCDay() == 1 && // monday
		    xdate.getUTCHours() == 0 &&
		    xdate.getUTCMinutes() == 0 &&
		    xdate.getUTCSeconds() == 0 &&
		    xdate.getUTCMilliseconds() == 0;
	    }
	    return test(new XDate(), 50) &&
		test(new XDate(), 21) &&
		test(new XDate(2011, 5, 5), 5) &&
		test(new XDate(2009, 12, 12), 13);
	}

	public setUTCWeek_with_year() : boolean{
	    function test(xdate : XDate , n : number , year : number ) {
		xdate.setUTCWeek(n, year);
		return xdate.getUTCWeek() == n &&
		    xdate.getUTCFullYear() == year &&
		    xdate.getUTCDay() == 1 && // monday
		    xdate.getUTCHours() == 0 &&
		    xdate.getUTCMinutes() == 0 &&
		    xdate.getUTCSeconds() == 0 &&
		    xdate.getUTCMilliseconds() == 0;
	    }
	    return test(new XDate(), 50, 2013) &&
		test(new XDate(), 21, 2014) &&
		test(new XDate(2011, 5, 5), 5, 1999) &&
		test(new XDate(2009, 12, 12), 13, 1995);
	}

	public setWeek_overflow() : boolean {
	    var xdate = new XDate(2012, 0, 3);
	    xdate.setWeek(54);
	    return xdate.getFullYear() == 2013 &&
		xdate.getWeek() == 2 &&
		xdate.getMonth() == 0 &&
		xdate.getDate() == 7;
	}

	public setWeek_underflow() : boolean {
	    var xdate = new XDate(2012, 0, 2); // a monday
	    return +xdate.clone().setWeek(0) == +xdate.clone().addWeeks(-1) &&
		+xdate.clone().setWeek(-1) == +xdate.clone().addWeeks(-2);
	}

	public setUTCWeek_correctly_handles_UTC_week_numbering_edge_case() : boolean{
	    var date = new XDate(Date.UTC(2010, 0, 3));

	    var wasWeek53 = date.getUTCWeek() === 53;
	    date.setUTCWeek(53);

	    return wasWeek53 && "Mon, 28 Dec 2009 00:00:00 GMT" === date.toUTCString();
	}

    }

    // based on xdate/test/utc-mode.js
    class utc_mode extends test_base
    {

	public identical_methods() : boolean {
	    var xdate = new XDate(true);
	    return xdate.getFullYear() == xdate.getUTCFullYear() &&
		xdate.getMonth() == xdate.getUTCMonth() &&
		xdate.getDate() == xdate.getUTCDate() &&
		xdate.getHours() == xdate.getUTCHours() &&
		xdate.getMinutes() == xdate.getUTCMinutes() &&
		xdate.getSeconds() == xdate.getUTCSeconds() &&
		xdate.getMilliseconds() == xdate.getUTCMilliseconds();
	}

	public getUTCMode() : boolean {
	    var xdate1 = new XDate(0, true);
	    var xdate2 = new XDate(0, false);
	    return xdate1.getUTCMode() && !xdate2.getUTCMode();
	}

	public setUTCMode_to_true() : boolean {
	    var xdate1 = new XDate();
	    var xdate2 = xdate1.clone().setUTCMode(true);
	    return !xdate1.getUTCMode() && xdate2.getUTCMode() && +xdate1 == +xdate2;
	}

	public setUTCMode_to_true_coerce() : boolean {
	    var xdate1 = new XDate();
	    var xdate2 = xdate1.clone().setUTCMode(true, true);
	    return !xdate1.getUTCMode() && xdate2.getUTCMode() &&
		(!xdate1.getTimezoneOffset() || xdate1.getTime() != xdate2.getTime()) &&
		(xdate1.getDate() == xdate2.getDate() && xdate2.getDate() == xdate2.getUTCDate()) &&
		(xdate1.getHours() == xdate2.getHours() && xdate2.getHours() == xdate2.getUTCHours());
	}

	public setUTCMode_to_false() : boolean {
	    var xdate1 = new XDate(2011, 5, 8, 0,0,0,0, true);
	    var xdate2 = xdate1.clone().setUTCMode(false);
	    return xdate1.getUTCMode() && !xdate2.getUTCMode() && +xdate1 == +xdate2;
	}

	public setUTCMode_to_false_coerce() : boolean {
	    var xdate1 = new XDate(2011, 7, 8, 0,0,0,0, true);
	    var xdate2 = xdate1.clone().setUTCMode(false, true);
	    return xdate1.getUTCMode() && !xdate2.getUTCMode() &&
		(!xdate1.getTimezoneOffset() || xdate1.getTime() != xdate2.getTime()) &&
		xdate1.getDate() == xdate2.getDate() &&
		xdate1.getHours() == xdate1.getHours();
	}

	public getTimezoneOffset() : boolean {
	    var date = new Date();
	    var xdate1 = new XDate(+date);
	    var xdate2 = new XDate(+date, true);
	    return xdate1.getTimezoneOffset() == date.getTimezoneOffset() &&
		!xdate2.getTimezoneOffset();
	}
    }

    // bases on xdate/test/utilities.js
    class utilities extends test_base
    {

	public clone() : boolean {
	    var d1 = new XDate();
	    var d2 = d1.clone();
	    d2.addMinutes(30);
	    return +d1 != +d2;
	}


	public clearTime() : boolean {
	    var d = new XDate(2010, 2, 5, 16, 15, 10, 100);
	    d.clearTime();
	    return !d.getHours() && !d.getMinutes() && !d.getSeconds() && !d.getMilliseconds();
	}


	public valid() : boolean {
	    var good = new XDate();
	    var bad = new XDate('asdf');
	    return good.valid() && !bad.valid();
	}


	public toDate_hasLocalTimezone_yes() : boolean {
	    var d = new Date(2012, 5, 8);
	    var xdate = new XDate(d);
	    return +xdate.toDate() == +d;
	}


	public toDate_hasLocalTimezone_no() : boolean {
	    var d = new Date(2012, 5, 8);
	    var xdate = new XDate(+d, false);
	    return +xdate.toDate() == +d;
	}


	public getDaysInMonth() : boolean {
	    return XDate.getDaysInMonth(2011, 1) == 28 && // feb
	    XDate.getDaysInMonth(2012, 1) == 29 && // feb, leap year
	    XDate.getDaysInMonth(2012, 8) == 30 && // sep
	    XDate.getDaysInMonth(2012, 6) == 31; // jul
	}


	public UTC_class_method() : boolean {
	    return Date.UTC(2011, 3, 20, 12, 30) == XDate.UTC(2011, 3, 20, 12, 30);
	}


	public parse_class_method() : boolean {
	    var s = "Sat Apr 23 2011 13:44:12 GMT-0700 (PDT)";
	    return Date.parse(s) == XDate.parse(s);
		//&&
	    //isNaN(Date.parse()) && isNaN(XDate.parse());
	}


	public now_class_method() : boolean {
	    return Math.abs(+new Date() - XDate.now()) < 1000;
	}


	public today_class_method() : boolean {
	    var xdate = XDate.today();
	    var d = new Date();
	    return xdate.getFullYear() == d.getFullYear() &&
		xdate.getMonth() == d.getMonth() &&
		xdate.getDate() == d.getDate() &&
		!xdate.getHours() &&
		!xdate.getSeconds() &&
		!xdate.getMilliseconds();
	}


	public toJSON() : boolean {
	    var realDate = new Date(2011, 3, 20, 12, 30);
	    var xdate = new Date(2011, 3, 20, 12, 30);
	    if (!realDate.toJSON) {
		return false;
	    }
	    return realDate.toJSON() == xdate.toJSON();
	}


	public chaining() : boolean {
	    var d = new XDate()
//		.setYear(99)
		.setFullYear(2011)
		.setWeek(50)
		.setMonth(1)
		.setDate(5)
		.setHours(12)
		.setMinutes(50)
		.setSeconds(20)
		.setMilliseconds(500)
		.setTime(0)
		.addYears(1)
		.addMonths(1)
		.addDays(1)
		.addMinutes(1)
		.addSeconds(1)
		.addMilliseconds(1)
		.clone()
		.clearTime()
		.setUTCFullYear(2010)
		.setUTCMonth(6)
		.setUTCWeek(5)
		.setUTCDate(4)
		.setUTCHours(12)
		.setUTCMinutes(30)
		.setUTCSeconds(30)
		.setUTCMilliseconds(10)
		.setUTCMode(true);
	    return d instanceof XDate;
	}

    }

}
