1563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark/*
2563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Copyright (C) 2004 Baron Schwartz <baron at sequent dot org>
3563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *
4563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * This program is free software; you can redistribute it and/or modify it
5563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * under the terms of the GNU Lesser General Public License as published by the
6563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * Free Software Foundation, version 2.1.
7563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark *
8563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * This program is distributed in the hope that it will be useful, but WITHOUT
9563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
11563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark * details.
12563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark */
13563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
14563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.parseFunctions = {count:0};
15563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.parseRegexes = [];
16563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.formatFunctions = {count:0};
17563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
18563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.prototype.dateFormat = function(format) {
19563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (Date.formatFunctions[format] == null) {
20563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        Date.createNewFormat(format);
21563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
22563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var func = Date.formatFunctions[format];
23563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return this[func]();
24563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
25563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
26563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.createNewFormat = function(format) {
27563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var funcName = "format" + Date.formatFunctions.count++;
28563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Date.formatFunctions[format] = funcName;
29563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var code = "Date.prototype." + funcName + " = function(){return ";
30563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var special = false;
31563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var ch = '';
32563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    for (var i = 0; i < format.length; ++i) {
33563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        ch = format.charAt(i);
34563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        if (!special && ch == "\\") {
35563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            special = true;
36563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        }
37563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        else if (special) {
38563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            special = false;
39563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            code += "'" + String.escape(ch) + "' + ";
40563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        }
41563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        else {
42563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            code += Date.getFormatCode(ch);
43563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        }
44563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
45563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    eval(code.substring(0, code.length - 3) + ";}");
46563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
47563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
48563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.getFormatCode = function(character) {
49563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    switch (character) {
50563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "d":
51563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "String.leftPad(this.getDate(), 2, '0') + ";
52563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "D":
53563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "Date.dayNames[this.getDay()].substring(0, 3) + ";
54563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "j":
55563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "this.getDate() + ";
56563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "l":
57563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "Date.dayNames[this.getDay()] + ";
58563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "S":
59563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "this.getSuffix() + ";
60563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "w":
61563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "this.getDay() + ";
62563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "z":
63563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "this.getDayOfYear() + ";
64563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "W":
65563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "this.getWeekOfYear() + ";
66563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "F":
67563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "Date.monthNames[this.getMonth()] + ";
68563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "m":
69563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
70563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "M":
71563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
72563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "n":
73563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "(this.getMonth() + 1) + ";
74563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "t":
75563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "this.getDaysInMonth() + ";
76563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "L":
77563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "(this.isLeapYear() ? 1 : 0) + ";
78563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "Y":
79563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "this.getFullYear() + ";
80563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "y":
81563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "('' + this.getFullYear()).substring(2, 4) + ";
82563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "a":
83563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "(this.getHours() < 12 ? 'am' : 'pm') + ";
84563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "A":
85563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
86563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "g":
87563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "((this.getHours() %12) ? this.getHours() % 12 : 12) + ";
88563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "G":
89563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "this.getHours() + ";
90563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "h":
91563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";
92563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "H":
93563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "String.leftPad(this.getHours(), 2, '0') + ";
94563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "i":
95563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "String.leftPad(this.getMinutes(), 2, '0') + ";
96563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "s":
97563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "String.leftPad(this.getSeconds(), 2, '0') + ";
98563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "O":
99563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "this.getGMTOffset() + ";
100563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "T":
101563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "this.getTimezone() + ";
102563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "Z":
103563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "(this.getTimezoneOffset() * -60) + ";
104563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    default:
105563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return "'" + String.escape(character) + "' + ";
106563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
107563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
108563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
109563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.parseDate = function(input, format) {
110563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (Date.parseFunctions[format] == null) {
111563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        Date.createParser(format);
112563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
113563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var func = Date.parseFunctions[format];
114563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return Date[func](input);
115563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
116563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
117563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.createParser = function(format) {
118563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var funcName = "parse" + Date.parseFunctions.count++;
119563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var regexNum = Date.parseRegexes.length;
120563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var currentGroup = 1;
121563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Date.parseFunctions[format] = funcName;
122563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
123563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var code = "Date." + funcName + " = function(input){\n"
124563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n"
125563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "var d = new Date();\n"
126563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "y = d.getFullYear();\n"
127563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "m = d.getMonth();\n"
128563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "d = d.getDate();\n"
129563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
130563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "if (results && results.length > 0) {"
131563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var regex = "";
132563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
133563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var special = false;
134563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var ch = '';
135563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    for (var i = 0; i < format.length; ++i) {
136563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        ch = format.charAt(i);
137563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        if (!special && ch == "\\") {
138563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            special = true;
139563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        }
140563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        else if (special) {
141563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            special = false;
142563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            regex += String.escape(ch);
143563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        }
144563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        else {
145563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            obj = Date.formatCodeToRegex(ch, currentGroup);
146563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            currentGroup += obj.g;
147563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            regex += obj.s;
148563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            if (obj.g && obj.c) {
149563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                code += obj.c;
150563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            }
151563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        }
152563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
153563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
154563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
155563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "{return new Date(y, m, d, h, i, s);}\n"
156563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
157563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "{return new Date(y, m, d, h, i);}\n"
158563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n"
159563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "{return new Date(y, m, d, h);}\n"
160563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "else if (y > 0 && m >= 0 && d > 0)\n"
161563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "{return new Date(y, m, d);}\n"
162563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "else if (y > 0 && m >= 0)\n"
163563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "{return new Date(y, m);}\n"
164563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "else if (y > 0)\n"
165563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "{return new Date(y);}\n"
166563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + "}return null;}";
167563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
168563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
169563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    eval(code);
170563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
171563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
172563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.formatCodeToRegex = function(character, currentGroup) {
173563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    switch (character) {
174563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "D":
175563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
176563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        c:null,
177563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
178563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "j":
179563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "d":
180563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
181563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"d = parseInt(results[" + currentGroup + "], 10);\n",
182563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(\\d{1,2})"};
183563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "l":
184563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
185563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
186563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(?:" + Date.dayNames.join("|") + ")"};
187563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "S":
188563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
189563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
190563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(?:st|nd|rd|th)"};
191563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "w":
192563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
193563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
194563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"\\d"};
195563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "z":
196563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
197563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
198563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(?:\\d{1,3})"};
199563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "W":
200563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
201563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
202563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(?:\\d{2})"};
203563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "F":
204563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
205563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
206563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(" + Date.monthNames.join("|") + ")"};
207563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "M":
208563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
209563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
210563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
211563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "n":
212563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "m":
213563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
214563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
215563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(\\d{1,2})"};
216563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "t":
217563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
218563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
219563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"\\d{1,2}"};
220563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "L":
221563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
222563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
223563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(?:1|0)"};
224563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "Y":
225563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
226563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"y = parseInt(results[" + currentGroup + "], 10);\n",
227563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(\\d{4})"};
228563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "y":
229563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
230563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
231563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
232563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(\\d{1,2})"};
233563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "a":
234563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
235563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"if (results[" + currentGroup + "] == 'am') {\n"
236563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                + "if (h == 12) { h = 0; }\n"
237563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                + "} else { if (h < 12) { h += 12; }}",
238563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(am|pm)"};
239563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "A":
240563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
241563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"if (results[" + currentGroup + "] == 'AM') {\n"
242563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                + "if (h == 12) { h = 0; }\n"
243563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark                + "} else { if (h < 12) { h += 12; }}",
244563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(AM|PM)"};
245563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "g":
246563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "G":
247563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "h":
248563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "H":
249563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
250563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"h = parseInt(results[" + currentGroup + "], 10);\n",
251563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(\\d{1,2})"};
252563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "i":
253563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
254563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"i = parseInt(results[" + currentGroup + "], 10);\n",
255563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(\\d{2})"};
256563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "s":
257563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:1,
258563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:"s = parseInt(results[" + currentGroup + "], 10);\n",
259563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"(\\d{2})"};
260563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "O":
261563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
262563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
263563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"[+-]\\d{4}"};
264563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "T":
265563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
266563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
267563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"[A-Z]{3}"};
268563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    case "Z":
269563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
270563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
271563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:"[+-]\\d{1,5}"};
272563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    default:
273563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        return {g:0,
274563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            c:null,
275563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            s:String.escape(character)};
276563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
277563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
278563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
279563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.prototype.getTimezone = function() {
280563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return this.toString().replace(
281563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace(
282563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
283563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
284563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
285563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.prototype.getGMTOffset = function() {
286563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return (this.getTimezoneOffset() > 0 ? "-" : "+")
287563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0")
288563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
289563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
290563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
291563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.prototype.getDayOfYear = function() {
292563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var num = 0;
293563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
294563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    for (var i = 0; i < this.getMonth(); ++i) {
295563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        num += Date.daysInMonth[i];
296563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
297563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return num + this.getDate() - 1;
298563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
299563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
300563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.prototype.getWeekOfYear = function() {
301563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    // Skip to Thursday of this week
302563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var now = this.getDayOfYear() + (4 - this.getDay());
303563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    // Find the first Thursday of the year
304563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var jan1 = new Date(this.getFullYear(), 0, 1);
305563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var then = (7 - jan1.getDay() + 4);
306563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    document.write(then);
307563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return String.leftPad(((now - then) / 7) + 1, 2, "0");
308563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
309563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
310563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.prototype.isLeapYear = function() {
311563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var year = this.getFullYear();
312563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
313563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
314563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
315563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.prototype.getFirstDayOfMonth = function() {
316563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var day = (this.getDay() - (this.getDate() - 1)) % 7;
317563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return (day < 0) ? (day + 7) : day;
318563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
319563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
320563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.prototype.getLastDayOfMonth = function() {
321563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
322563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return (day < 0) ? (day + 7) : day;
323563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
324563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
325563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.prototype.getDaysInMonth = function() {
326563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
327563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return Date.daysInMonth[this.getMonth()];
328563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
329563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
330563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.prototype.getSuffix = function() {
331563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    switch (this.getDate()) {
332563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        case 1:
333563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        case 21:
334563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        case 31:
335563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            return "st";
336563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        case 2:
337563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        case 22:
338563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            return "nd";
339563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        case 3:
340563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        case 23:
341563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            return "rd";
342563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        default:
343563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark            return "th";
344563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
345563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
346563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
347563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkString.escape = function(string) {
348563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return string.replace(/('|\\)/g, "\\$1");
349563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
350563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
351563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkString.leftPad = function (val, size, ch) {
352563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var result = new String(val);
353563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    if (ch == null) {
354563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        ch = " ";
355563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
356563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    while (result.length < size) {
357563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark        result = ch + result;
358563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    }
359563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    return result;
360563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
361563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
362563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
363563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.monthNames =
364563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark   ["January",
365563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "February",
366563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "March",
367563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "April",
368563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "May",
369563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "June",
370563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "July",
371563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "August",
372563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "September",
373563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "October",
374563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "November",
375563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "December"];
376563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.dayNames =
377563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark   ["Sunday",
378563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "Monday",
379563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "Tuesday",
380563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "Wednesday",
381563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "Thursday",
382563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "Friday",
383563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    "Saturday"];
384563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.y2kYear = 50;
385563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.monthNumbers = {
386563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Jan:0,
387563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Feb:1,
388563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Mar:2,
389563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Apr:3,
390563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    May:4,
391563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Jun:5,
392563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Jul:6,
393563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Aug:7,
394563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Sep:8,
395563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Oct:9,
396563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Nov:10,
397563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    Dec:11};
398563af33bc48281d19dce701398dbb88cb54fd7ecCary ClarkDate.patterns = {
399563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    ISO8601LongPattern:"Y-m-d H:i:s",
400563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    ISO8601ShortPattern:"Y-m-d",
401563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    ShortDatePattern: "n/j/Y",
402563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    LongDatePattern: "l, F d, Y",
403563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    FullDateTimePattern: "l, F d, Y g:i:s A",
404563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    MonthDayPattern: "F d",
405563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    ShortTimePattern: "g:i A",
406563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    LongTimePattern: "g:i:s A",
407563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    SortableDateTimePattern: "Y-m-d\\TH:i:s",
408563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    UniversalSortableDateTimePattern: "Y-m-d H:i:sO",
409563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    YearMonthPattern: "F, Y"};
410563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
411563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkvar date = new Date("1/1/2007 1:11:11");
412563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark
413563af33bc48281d19dce701398dbb88cb54fd7ecCary Clarkfor (i = 0; i < 4000; ++i) {
414563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var shortFormat = date.dateFormat("Y-m-d");
415563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    var longFormat = date.dateFormat("l, F d, Y g:i:s A");
416563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark    date.setTime(date.getTime() + 84266956);
417563af33bc48281d19dce701398dbb88cb54fd7ecCary Clark}
418