var DateTimeKind = new Object();
Object.Extend(DateTimeKind,
    {
    Unspecified: 0,
    Utc: 1,
    Local: 2
    });
    
var DateTimeFormat = new Object();
Object.Extend(DateTimeFormat,
    {
    DayNames: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
    DayNamesAbbreviated: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
    MonthNames: ["", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
    MonthNamesAbbreviated: ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
    });
    
var TimeSpan = Class.Create();
TimeSpan.prototype =
    {
    Initialize: function()
        {
        switch (arguments.length)
            {
            case 1:
                var ticks = arguments[0];
                this._ticks = ticks;
                break;
            case 3:
                var hours = arguments[0];
                var minutes = arguments[1];
                var seconds = arguments[2];
                this._ticks = DateTime.TimeToTicks(hours, minutes, seconds);
                break;
            case 4:
            case 5:
                var days = arguments[0];
                var hours = arguments[1];
                var minutes = arguments[2];
                var seconds = arguments[3];
                var milliseconds = arguments[4];
                var num = parseInt(((((((days * 0xe10) * 0x18) + (hours * 0xe10)) + (minutes * 60)) + seconds) * 0x3e8) + milliseconds);
                if ((num > 0x346dc5d638865) || (num < -922337203685477))
                    {
                    throw new ArgumentException(null, "Specified argument was out of the range of valid values");
                    }
                this._ticks = parseInt(num * 0x2710);
                break;
            }
            
        this.Days = parseInt(this._ticks / 0xc92a69c000);
        this.Hours = parseInt(((this._ticks / 0x861c46800) % (0x18)));
        this.Milliseconds = parseInt((((this._ticks / (0x2710)) % (0x3e8))));
        this.Minutes = parseInt(((this._ticks / (0x23c34600)) % (60)));
        this.Seconds = parseInt(((this._ticks / (0x989680)) % (60)));
        this.Ticks = this._ticks;
        this.TotalDays = parseFloat((this._ticks * 1.1574074074074074E-12));
        this.TotalHours = parseFloat((this._ticks * 2.7777777777777777E-11));
        this.TotalMilliseconds = function()
            {
            var num = this._ticks * 0.0001;
            if (num > 922337203685477)
                {
                return 922337203685477;
                }
            if (num < -922337203685477)
                {
                return -922337203685477;
                }
            return parseFloat(num);
            }.call(this);
        this.TotalMinutes = parseFloat((this._ticks * 1.6666666666666667E-09));
        this.TotalSeconds = parseFloat((this._ticks * 1E-07));
        },
    _ticks: null,
    Days: null,
    Hours: null,
    Milliseconds: null,
    Minutes: null,
    Seconds: null,
    Ticks: null,
    TotalDays: null,
    TotalHours: null,
    TotalMilliseconds: null,
    TotalMinutes: null,
    TotalSeconds: null,
    Add: function(ts)
        {
        var ticks = this._ticks + ts._ticks;
        if (((this._ticks >> 0x3f) == (ts._ticks >> 0x3f)) && ((this._ticks >> 0x3f) != (ticks >> 0x3f)))
            {
            throw new ArgumentException(null, "Specified argument was out of the range of valid values");
            }
        return new TimeSpan(ticks);
        },
    ToString: function()
        {
        var builder = "";
        var num = parseInt((this._ticks / 0xc92a69c000));
        var num2 = parseInt(this._ticks % 0xc92a69c000);
        if (this._ticks < 0)
            {
            builder += "-";
            num = -num;
            num2 = -num;
            }
        if (num != 0)
            {
            builder += num;
            builder += ".";
            }
        builder += parseInt(((num2 / 0x861c46800) % (0x18))).toPaddedString(2);
        builder += ":";
        builder += parseInt(((num2 / 0x23c34600) % (60))).toPaddedString(2);
        builder += ":";
        builder += parseInt(((num2 / 0x989680) % (60))).toPaddedString(2);
        var n = parseInt((num2 % (0x989680)));
        if (n != 0)
            {
            builder += ".";
            builder += n.toPaddedString(7);
            }
        return builder;
        },
    Subtract: function(ts)
        {
        var ticks = this._ticks - ts._ticks;
        if (((this._ticks >> 0x3f) != (ts._ticks >> 0x3f)) && ((this._ticks >> 0x3f) != (ticks >> 0x3f)))
            {
            throw new ArgumentException(null, "Specified argument was out of the range of valid values");
            }
        return new TimeSpan(ticks);
        },
    Equals: function(obj)
        {
        return (this._ticks == obj._ticks);
        },
    Negate: function()
        {
        if (this._ticks == MinValue._ticks)
            {
            throw new ArgumentException(null, "Specified argument was out of the range of valid values");
            }
        return new TimeSpan(-this._ticks);
        },
    Duration: function()
        {
        if (this._ticks == TimeSpan.MinValue._ticks)
            {
            throw new ArgumentException(null, "Specified argument was out of the range of valid values");
            }
        return new TimeSpan((this._ticks >= 0) ? this._ticks : -this._ticks);
        }
    }
    
TimeSpan.MinValue = new TimeSpan(-9223372036854775808);
TimeSpan.MaxValue = new TimeSpan(0x7fffffffffffffff);
TimeSpan.Zero = new TimeSpan(0);
TimeSpan.Equals = function(t1, t2)
    {
    return (t1._ticks == t2._ticks);
    }
TimeSpan.FromTicks = function(value)
    {
    return new TimeSpan(value);
    }
TimeSpan.FromSeconds = function(value)
    {
    return TimeSpan.Interval(value, 0x3e8);
    }
TimeSpan.FromMinutes = function(value)
    {
    return TimeSpan.Interval(value, 0xea60);
    }
TimeSpan.FromMilliseconds = function(value)
    {
    return TimeSpan.Interval(value, 1);
    }
TimeSpan.FromHours = function(value)
    {
    return TimeSpan.Interval(value, 0x36ee80);
    }
TimeSpan.FromDays = function(value)
    {
    return TimeSpan.Interval(value, 0x5265c00);
    }
TimeSpan.Compare = function(t1, t2)
    {
    if (t1._ticks > t2._ticks)
        {
        return 1;
        }
    if (t1._ticks < t2._ticks)
        {
        return -1;
        }
    return 0;
    }
TimeSpan.Interval = function(value, scale)
    {
    if (isNaN(value))
        {
        throw new ArgumentException(null, "Specified argument was out of the range of valid values");
        }
    var num = parseFloat(value * scale);
    var num2 = parseFloat(num + ((value >= 0) ? 0.5 : -0.5));
    if ((num2 > 922337203685477) || (num2 < -922337203685477))
        {
        throw new ArgumentException(null, "Specified argument was out of the range of valid values");
        }
    return new TimeSpan(parseInt((num2) * 0x2710));
    }

var DateTime = Class.Create();
Object.Extend(DateTime,
    {
    DaysToMonth365: [0, 0x1f, 0x3b, 90, 120, 0x97, 0xb5, 0xd4, 0xf3, 0x111, 0x130, 0x14e, 0x16d],
    DaysToMonth366: [0, 0x1f, 60, 0x5b,0x79, 0x98, 0xb6, 0xd5, 0xf4, 0x112, 0x131, 0x14f, 0x16e],
    InstanceCount: 0
    });
    
DateTime.prototype =
    {
    Initialize: function()
        {
        switch (arguments.length)
            {
            case 1:
                var ticks = arguments[0];
                if ((ticks < 0) || (ticks > 0x2bca2875f4373fff))
                    {
                    throw new ArgumentException("ticks", "Specified argument was out of the range of valid values");
                    }
                this.dateData = ticks;
                break;
            case 2:
                var ticks = arguments[0];
                var kind = arguments[1];
                if ((ticks < 0) || (ticks > 0x2bca2875f4373fff))
                    {
                    throw new ArgumentException("ticks", "Specified argument was out of the range of valid values");
                    }
                if ((kind < DateTimeKind.Unspecified) || (kind > DateTimeKind.Local))
                    {
                    throw new ArgumentException("kind", "Spcified argument was out of the range of valid values");
                    }
                this.dateData = (ticks || ((kind) << 0x3e));
                break;
            case 3:
                var year = arguments[0];
                var month = arguments[1];
                var day = arguments[2];
                if (day.constructor == Number)
                    {
                    this.dateData = DateTime.DateToTicks(year, month, day);
                    }
                else
                    {
                    if ((year < 0) || (year > 0x2bca2875f4373fff))
                        {
                        throw new ArgumentException("ticks", "Specified argument was out of the range of valid values");
                        }
                    this.dateData = (year || (day ? -4611686018427387904 : -9223372036854775808));
                    }
                break;
            case 6:
                var year = arguments[0];
                var month = arguments[1];
                var day = arguments[2];
                var hour = arguments[3];
                var minute = arguments[4];
                var second = arguments[5];
                this.dateData = (DateTime.DateToTicks(year, month, day) + DateTime.TimeToTicks(hour, minute, second));
                break;
            case 7:
                var year = arguments[0];
                var month = arguments[1];
                var day = arguments[2];
                var hour = arguments[3];
                var minute = arguments[4];
                var second = arguments[5];
                var kind = arguments[6];
                var num = DateTime.DateToTicks(year, month, day) + DateTime.TimeToTicks(hour, minute, second);
                if ((kind < DateTimeKind.Unspecified) || (kind > DateTimeKind.Local))
                    {
                    throw new ArgumentException("kind", "Spcified argument was out of the range of valid values");
                    }
                this.dateData = (num || ((kind) << 0x3e));
                break;
            case 8:
                var year = arguments[0];
                var month = arguments[1];
                var day = arguments[2];
                var hour = arguments[3];
                var minute = arguments[4];
                var second = arguments[5];
                var millisecond = arguments[6];
                var kind = arguments[7];
                var num = DateTime.DateToTicks(year, month, day) + DateTime.TimeToTicks(hour, minute, second);
                if ((millisecond < 0) || (millisecond > 0x3e8))
                    {
                    throw new ArgumentException("kind", "Spcified argument was out of the range of valid values");
                    }
                num += millisecond * 0x2710;
                if ((num < 0) || (num > 0x2bca2875f4373fff))
                    {
                    throw new ArgumentException("kind", "Spcified argument was out of the range of valid values");
                    }
                if ((kind < DateTimeKind.Unspecified) || (kind > DateTimeKind.Local))
                    {
                    throw new ArgumentException("kind", "Spcified argument was out of the range of valid values");
                    }
                this.dateData = (num || ((kind) << 0x3e));
                break;
            default:
                this.dateData = DateTime.MinValue.Ticks;
                break;
            }
            
        this.InternalTicks = ((this.dateData)); // & 0x3fffffffffffffff);
        this.InternalKind = (this.dateData & 13835058055282163712);
        try
            {
            DateTime.InstanceCount++;
            if (DateTime.InstanceCount < 5)
                {
                this.Date = new DateTime((this.InternalTicks - (this.InternalTicks % 0xc92a69c000)));
                }
            else
                {
                DateTime.InstanceCount = 0;
                }
            }
        catch (ex)
            {
            }
        this.Day = this.GetDatePart(3);
        this.DayOfWeek = parseInt(((((this.InternalTicks / 0xc92a69c000) + 1) % (7))));
        this.DayOfYear = this.GetDatePart(1);
        this.Hour = parseInt(((Math.floor(this.InternalTicks / 0x861c46800)) % (0x18)));
        this.Kind = function()
            {
            switch (this.InternalKind)
                {
                case 0:
                    return DateTimeKind.Unspecified;
                case 0x4000000000000000:
                    return DateTimeKind.Utc;
                }
            return DateTimeKind.Local;
            }.call(this);
        this.Millisecond = parseInt(((this.InternalTicks / (0x2710)) % (0x3e8)));
        this.Minute = parseInt(((this.InternalTicks / (0x23c34600)) % (60)));
        this.Month = this.GetDatePart(2);
        this.Second = parseInt(((this.InternalTicks / (0x989680)) % (60)));
        this.Ticks = this.InternalTicks;
        this.Year = this.GetDatePart(0);
        this.TimeOfDay = new TimeSpan(this.InternalTicks % 0xc92a69c000);
        this.JSDate = new Date(this.Year, this.Month - 1, this.Day, this.Hour, this.Minute, this.Second, this.Millisecond);
        },
    GetDatePart: function(part)
        {
        var num2 = parseInt(Math.floor(this.InternalTicks / 0xc92a69c000));
        var num3 = parseInt(Math.floor(num2 / 0x23ab1));
        num2 -= parseInt(num3 * 0x23ab1);
        var num4 = parseInt(num2 / 0x8eac);
        if (num4 == 4)
            {
            num4 = 3;
            }
        num2 -= parseInt(num4 * 0x8eac);
        var num5 = parseInt(num2 / 0x5b5);
        num2 -= parseInt(num5 * 0x5b5);
        var num6 = parseInt(num2 / 0x16d);
        if (num6 == 4)
            {
            num6 = 3;
            }
        if (part == 0)
            {
            return parseInt((((((num3 * 400) + (num4 * 100)) + (num5 * 4)) + num6) + 1));
            }
        num2 -= parseInt(num6 * 0x16d);
        if (part == 1)
            {
            return (num2 + 1);
            }
        var numArray = ((num6 == 3) && ((num5 != 0x18) || (num4 == 3))) ? DateTime.DaysToMonth366 : DateTime.DaysToMonth365;
        var index = num2 >> 6;
        while (num2 >= numArray[index])
            {
            index++;
            }
        if (part == 2)
            {
            return index;
            }
        return parseInt(((num2 - numArray[index - 1]) + 1));
        },
    ToLocalTime: function()
        {
        if (this.Kind == DateTimeKind.Local)
            {
            return this;
            }
        var isAmbiguousLocalDst = false;
        var utcOffsetFromUniversalTime = 0;
        return new DateTime(this.Ticks + utcOffsetFromUniversalTime, DateTimeKind.Local, isAmbiguousLocalDst);
        },
    InternalTicks: null,
    InternalKind: null,
    Date: null,
    Day: null,
    DayOfWeek: null,
    DayOfYear: null,
    Hour: null,
    Kind: null,
    Millisecond: null,
    Minute: null,
    Month: null,
    Second: null,
    Ticks: null,
    TimeOfDay: null,
    Year: null,
    dateData: null,
    JSDate: null,
    AddTicks: function(value)
        {
        var internalTicks = this.InternalTicks;
        if ((value > (0x2bca2875f4373fff - internalTicks)) || (value < -internalTicks))
            {
            throw new ArgumentException("value", "Specified argument was out of the range of valid values");
            }
        return new DateTime(parseInt(internalTicks + value));
        },
    AddMonths: function(months)
        {
        if ((months < -120000) || (months > 0xd4c0))
            {
            throw new ArgumentException("months", "Specified argument was out of the range of valid values");
            }
        var datePart = this.GetDatePart(0);
        var month = this.GetDatePart(2);
        var day = this.GetDatePart(3);
        var num4 = parseInt((month - 1) + months);
        if (num4 >= 0)
            {
            month = parseInt((num4 % 12) + 1);
            datePart += parseInt(num4 / 12);
            }
        else
            {
            month = 12 + parseInt(((num4 + 1) % 12));
            datePart += parseInt((num4 - 11) / 12);
            }
        if ((datePart < 1) || (datePart > 0x270f))
            {
            throw new ArgumentException("months", "Specified argument was out of the range of valid values");
            }
        var num5 = this.DaysInMonth(datePart, month);
        if (day > num5)
            {
            day = num5;
            }
        return new DateTime(parseInt((DateTime.DateToTicks(datePart, month, day)) + (this.InternalTicks % 0xc92a69c000)));
        },
    AddYears: function(value)
        {
        if ((value < -10000) || (value > 0x2710))
            {
            throw new ArgumentException("months", "Specified argument was out of the range of valid values");
            }
        return this.AddMonths(parseInt(value * 12));
        },
    Add: function(value)
        {
        return this.AddTicks(value._ticks);
        },
    _Add: function(value, scale)
        {
        var num = parseInt(((value * scale) + ((value >= 0) ? 0.5 : -0.5)));
        if ((num <= -315537897600000) || (num >= 0x11efae44cb400))
            {
            throw new ArgumentException("value", "Specified argument was out of the range of valid values");
            }
        return this.AddTicks((parseInt(num * 0x2710)));
        },
    AddDays: function(value)
        {
        return this._Add(value, 0x5265c00);
        },
    AddHours: function(value)
        {
        return this._Add(value, 0x36ee80);
        },
    AddMinutes: function(value)
        {
        return this._Add(value, 0xea60);
        },
    AddSeconds: function(value)
        {
        return this._Add(value, 0x3e8);
        },
    AddMilliseconds: function(value)
        {
        return this._Add(value, 1);
        },
    DaysInMonth: function(year, month)
        {
        if ((month < 1) || (month > 12))
            {
            throw new ArgumentException("month", "Specified argument was out of the range of valid values");
            }
        var numArray = DateTime.IsLeapYear(year) ? DateTime.DaysToMonth366 : DateTime.DaysToMonth365;
        return (numArray[month] - numArray[month - 1]);
        },
    Equals: function(value)
        {
        if (value instanceof DateTime)
            {
            return (this.InternalTicks == value.InternalTicks);
            }
        return false;
        },
    Subtract: function(value)
        {
        if (value instanceof TimeSpan)
            {
            var internalTicks = this.InternalTicks;
            var num2 = parseInt(value._ticks);
            if ((internalTicks < num2) || ((internalTicks - 0x2bca2875f4373fff) > num2))
                {
                throw new ArgumentException(null, "Specified argument was out of the range of valid values");
                }
            return new DateTime(parseInt(internalTicks - num2));
            }
        else
            {
            return new TimeSpan(this.InternalTicks - value.InternalTicks);
            }
        },
    ToString: function(format)
        {
        if (format == null)
            {
            format = "dd MMMM yyyy HH:mm:ss";
            }
        if (format.length == 0)
            {
            format = "dd MMMM yyyy HH:mm:ss";
            }
        var v = new Object();
        var d = this;
        if (d.Year.length < 4)
            {
            d.Year = "" + (d.Year - 0 + 1900);
            }
        v["y"] = "" + d.Year.ToPaddedString(4);
        v["yyyy"] = d.Year.ToPaddedString(4);
        v["yy"] = d.Year.ToPaddedString(4).substr(2, 4);
        v["M"] = d.Month;
        v["MM"] = d.Month.ToPaddedString(2);
        v["MMM"] = DateTimeFormat.MonthNamesAbbreviated[d.Month];
        v["MMMM"] = DateTimeFormat.MonthNames[d.Month];
        v["d"] = d.Day;
        v["dd"] = d.Day.ToPaddedString(2);
        v["ddd"] = DateTimeFormat.DayNamesAbbreviated[d.DayOfWeek];
        v["dddd"] = DateTimeFormat.DayNames[d.DayOfWeek];
        v["H"] = d.Hour;
        v["HH"] = d.Hour.ToPaddedString(2);
        if (d.Hour == 0)
            {
            v["h"] = 12;
            }
        else if (d.Hour > 12)
            {
            v["h"] = d.Hour - 12;
            }
        else
            {
            v["h"] = d.Hour;
            }
        v["hh"] = v["h"].ToPaddedString(2);
        if (d.Hour > 11)
            {
            v["a"] = "PM";
            }
        else
            {
            v["a"] = "AM";
            }
        v["m"] = d.Minute;
        v["mm"] = v["m"].ToPaddedString(2);
        v["s"] = d.Second;
        v["ss"] = v["s"].ToPaddedString(2);
        
        var pos = 0;
        var ch = "";
        var token;
        var result = "";
        while (pos < format.length)
            {
            ch = format.charAt(pos);
            token = "";
            while ((format.charAt(pos) == ch) && (pos < format.length))
                {
                token += format.charAt(pos++);
                }
            if (v[token] != null)
                {
                result = result + v[token];
                }
            else
                {
                result = result + token;
                }
            }
        return result;
        },
    ToShortDateString: function()
        {
        return this.ToString("dd/MM/yyyy");
        },
    ToShortTimeString: function()
        {
        return this.ToString("HH:mm");
        },
    ToRFC1123DateTimeString: function()
        {
        return this.ToString("ddd, dd MMM yyyy HH:mm:ss") + " GMT";
        },
    ToSortableDateTimeString: function()
        {
        return this.ToString("yyyy-MM-ddTHH:mm:ss");
        },
    ToUniversalSortableDateTimeString: function()
        {
        return this.ToString("yyyy-MM-dd HH:mm:ssZ");
        },
    ToLongDateString: function()
        {
        return this.ToString("dd MMMM yyyy");
        },
    ToLongTimeString: function()
        {
        return this.ToString("HH:mm:ss");
        }
    }
    
DateTime.MinValue = new DateTime(0, DateTimeKind.Unspecified);
DateTime.MaxValue = new DateTime(0x2bca2875f4373fff, DateTimeKind.Unspecified);
DateTime.DateToTicks = function(year, month, day)
    {
    if (((year >= 1) && (year <= 0x270f)) && ((month >= 1) && (month <= 12)))
        {
        var numArray = DateTime.IsLeapYear(year) ? DateTime.DaysToMonth366 : DateTime.DaysToMonth365;
        if ((day >= 1) && (day <= (numArray[month] - numArray[month - 1])))
            {
            var num = year - 1;
            var num2 = parseInt(((((((num * 0x16d) + (parseInt(num / 4))) - (parseInt(num / 100))) + (parseInt(num / 400))) + numArray[month - 1]) + day) - 1);
            return (num2 * 0xc92a69c000);
            }
        }
    throw new ArgumentException(null, "Specified argument was out of the range of valid values");
    };
DateTime.Compare = function(t1, t2)
    {
    var internalTicks = t1.InternalTicks;
    var num2 = t2.InternalTicks;
    if (internalTicks > num2)
        {
        return 1;
        }
    if (internalTicks < num2)
        {
        return -1;
        }
    return 0;
    };
DateTime.Equals = function(dateTime1, dateTime2)
    {
    return (dateTime1.InternalTicks == dateTime2.InternalTicks);
    };
DateTime.TimeToTicks = function(hour, minute, second)
    {
    if ((((hour < 0) || (hour > 0x18)) || ((minute < 0) || (minute >= 60))) || ((second < 0) || (second >= 60)))
        {
        throw new ArgumentException(null, "Specified argument was out of the range of valid values");
        }
    var num = ((hour * 0xe10) + (minute * 60)) + second;
    if ((num > 0xd6bf94d5e5) || (num < -922337203685))
        {
        throw new ArgumentException(null, "Specified argument was out of the range of valid values");
        }
    return (num * 0x989680);
    };
DateTime.IsLeapYear = function(year)
    {
    if ((year < 1) || (year > 0x270f))
        {
        throw new ArgumentException("year", "Specified argument was out of the range of valid values");
        }
    if ((year % 4) != 0)
        {
        return false;
        }
    if ((year % 100) == 0)
        {
        return ((year % 400) == 0);
        }
    return true;
    };
DateTime.UtcNow = function()
    {
    var dt = new Date();
    return new DateTime(dt.getFullYear(), (dt.getMonth() + 1), dt.getDate(), dt.getHours(), dt.getMinutes(), dt.getSeconds(), dt.getMilliseconds(), DateTimeKind.Utc);
    }.call(this);
DateTime.Now = DateTime.UtcNow.ToLocalTime();
DateTime.Today = DateTime.Now.Date;
DateTime.Parse = function(s)
    {
    var time;
    if (s == null)
        {
        return false;
        }
    if (s.length == 0)
        {
        return false;
        }
    var checkList = [
        ["y-M-d", "MMM d, y", "MMM d,y", "y-MMM-d", "d-MMM-y", "MMM d"],
        ["d/M/y", "d-M-y", "d.M.y", "d-MMM", "d/M", "d-M", "ddMMyy", "ddMMyyyy"],
        ["M/d/y", "M-d-y", "M.d.y", "MMM-d", "M/d", "M-d", "MMddyy", "MMddyyyy"]
        ];
        
    var d = null;
    for (var i = 0; i < checkList.length; i++)
        {
        var item = checkList[i];
        for (var j = 0; j < item.length; j++)
            {
            d = ParseDateFromFormat(s, item[j]);
            if (!isNaN(d))
                {
                return new DateTime(d);
                }
            }
        }
    return DateTime.MinValue;
    // helper functions
    function ParseDateFromFormat(sDate, sFormat)
        {
        var pos = 0;
        var idx = 0;
        var ch = "";
        var token = "";
        var x, y;
        var internalDate = new Object();
        
        internalDate.Now = new DateTime();
        internalDate.Year = 1;
        internalDate.Month = 1;
        internalDate.Date = 1;
        internalDate.Hours = 0;
        internalDate.Minutes = 0;
        internalDate.Seconds = 0;
        internalDate.AM = false;
        internalDate.PM = false;
        
        while (pos < sFormat.length)
            {
            // get the next token from the string
            ch = sFormat.charAt(pos);
            token = "";
            while ((sFormat.charAt(pos) == ch) && (pos < sFormat.length))
                {
                token += sFormat.charAt(pos++);
                }
                
            // extract contents of value based on format token
            if (token == "yyyy" || token == "yy" || token == "y")
                {
                if (token == "yyyy")
                    {
                    x = 4;
                    y = 4;
                    }
                if (token == "yy")
                    {
                    x = 2;
                    y = 2;
                    }
                if (token == "y")
                    {
                    x = 2;
                    y = 4;
                    }
                internalDate.Year = GetIntFromString(sDate, idx, x, y);
                if (internalDate.Year == null)
                    {
                    return NaN;
                    }
                idx += internalDate.Year.length;
                if (internalDate.Year.length == 2)
                    {
                    var _x = internalDate.Year % 100;
                    if (_x < 38)
                        {
                        internalDate.Year = 2000 + (internalDate.Year - 0);
                        }
                    else
                        {
                        internalDate.Year = 1900 + (internalDate.Year - 0);
                        }
                    }
                }
            else if (token == "MMMM" || token == "MMM")
                {
                internalDate.Month = 0;
                for (var i = 0; i < 12; i++)
                    {
                    var monthName = (token == "MMMM") ? DateTimeFormat.MonthNames[i + 1] : DateTimeFormat.MonthNamesAbbreviated[i + 1];
                    if (sDate.substr(idx, idx + monthName.length).toLowerCase() == monthName.toLowerCase())
                        {
                        if (token == "MMMM" || token == "MMM")
                            {
                            internalDate.Month = i + 1;
                            if (internalDate.Month > 12)
                                {
                                internalDate.Month -= 12;
                                }
                            idx += monthName.length;
                            break;
                            }
                        }
                    }
                if ((internalDate.Month < 1) || (internalDate.Month > 12))
                    {
                    return NaN;
                    }
                }
            else if (token == "dddd" || token == "ddd")
                {
                for (var i = 0; i < 7; i++)
                    {
                    var dayName = (token == "dddd") ? DateTimeFormat.DayNames[i] : DateTimeFormat.DayNamesAbbreviated[i];
                    if (sDate.substr(idx, idx + dayName.length).toLowerCase() == dayName.toLowerCase())
                        {
                        idx += dayName.length;
                        break;
                        }
                    }
                }
            else if (token == "MM" || token == "M")
                {
                internalDate.Month = GetIntFromString(sDate, idx, token.length, 2);
                if (internalDate.Month == null || (internalDate.Month < 1) || (internalDate.Month > 12))
                    {
                    return NaN;
                    }
                idx += internalDate.Month.length;
                }
            else if (token == "dd" || token == "d") 
                {
			    internalDate.Date = GetIntFromString(sDate, idx, token.length, 2);
			    if (internalDate.Date == null || (internalDate.Date < 1) || (internalDate.Date > 31))
			        {
			        return NaN;
			        }
			    idx += internalDate.Date.length;
			    }
            else if (token == "hh" || token == "h") 
                {
			    internalDate.Hour = GetIntFromString(sDate, idx, token.length, 2);
			    if (internalDate.Hour == null || (internalDate.Hour < 1) || (internalDate.Hour > 12))
			        {
			        return NaN;
			        }
			    idx += internalDate.Hour.length;
			    }
		    else if (token=="HH"||token=="H") 
		        {
			    internalDate.Hour = GetIntFromString(sDate, idx, token.length, 2);
			    if (internalDate.Hour == null || (internalDate.Hour < 0) || (internalDate.Hour > 23))
			        {
			        return NaN;
			        }
			    idx += internalDate.Hour.length;
			    }
		    else if (token == "mm" || token == "m") 
		        {
			    internalDate.Minute = GetIntFromString(sDate, idx, token.length, 2);
			    if (internalDate.Minute == null || (internalDate.Minute < 0) || (internalDate.Minute > 59))
			        {
			        return NaN;
			        }
			    idx += internalDate.Minute.length;
			    }
		    else if (token == "ss" || token == "s") 
		        {
			    internalDate.Second = GetIntFromString(sDate, idx, token.length, 2);
			    if (internalDate.Second == null || (internalDate.Second < 0) || (internalDate.Second > 59))
			        {
			        return NaN;
			        }
			    idx += internalDate.Second.length;
			    }
		    else if (token == "a") 
		        {
			    if (sDate.substring(idx, idx + 2).toLowerCase() == "am") 
			        {
			        internalDate.AM = true;
			        }
			    else if (sDate.substring(idx, idx + 2).toLowerCase() == "pm") 
			        {
			        internalDate.PM = true;
			        }
			    else 
			        {
			        return NaN;
			        }
			    idx += 2;
			    }
		    else 
		        {
			    if (sDate.substring(idx, idx + token.length) != token) 
			        {
			        return NaN;
			        }
			    else 
			        {
			        idx += token.length;
			        }
			    }
			}
			
		if (idx != sDate.length)
		    {
		    return NaN;
		    }
		    
		// is the date valid for the month
		internalDate.Month = internalDate.Month - 0;
		internalDate.Date = internalDate.Date - 0;
		internalDate.Hours = internalDate.Hours - 0;
		internalDate.Minutes = internalDate.Minutes - 0;
		internalDate.Seconds = internalDate.Seconds - 0;
		if (internalDate.Month == 2)
		    {
		    if (DateTime.IsLeapYear(internalDate.Year))
		        {
		        if (internalDate.Date > 29)
		            {
		            return NaN;
		            }
		        }
	        else
	            {
	            if (internalDate.Date > 28)
	                {
	                return NaN;
	                }
	            }
		    }
		if ((internalDate.Month == 4) || (internalDate.Month == 6) || (internalDate.Month == 9) || (internalDate.Month == 11))
		    {
		    if (internalDate.Date > 30)
		        {
		        return NaN;
		        }
		    }
		    
		if (internalDate.Hours < 12 && internalDate.PM)
		    {
		    internalDate.Hours += 12;
		    }
		else if (internalDate.Hours > 11 && internalDate.AM)
		    {
		    internalDate.Hours -= 12;
		    }
		    
		var newDate = new DateTime(internalDate.Year, internalDate.Month, internalDate.Date, internalDate.Hours, internalDate.Minutes, internalDate.Seconds, DateTimeKind.Unspecified);
		return newDate.Ticks;
        }
    function GetIntFromString(str, i, min, max)
        {
        for (var x = max; x >= min; x--)
            {
            var token = str.substring(i, i + x);
            if (token.length < min)
                {
                return null;
                }
            if (IsInteger(token))
                {
                return token;
                }
            }
        return null;
        };
    function IsInteger(val)
        {
        var digits = "1234567890"
        for (var i = 0; i < val.length; i++)
            {
            if (digits.indexOf(val.charAt(i)) == -1)
                {
                return false;
                }
            }
        return true;
        };
    };
    
var ArgumentException = Class.Create();
Object.Extend(ArgumentException.prototype,
    {
    initialize: function(paramName, message)
        {
        this.ParamName = paramName;
        this.Message = message;
        },
    ParamName: "",
    Message: ""
    });

