Diffstat (limited to 'frontend/beta/js/YUI-extensions/Date.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/beta/js/YUI-extensions/Date.js | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/frontend/beta/js/YUI-extensions/Date.js b/frontend/beta/js/YUI-extensions/Date.js new file mode 100644 index 0000000..f79c8a5 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/Date.js | |||
@@ -0,0 +1,407 @@ | |||
1 | /* | ||
2 | * All the Date functions below are the excellent work of Baron Schwartz | ||
3 | * They generate precompiled functions from date formats instead of parsing and processing | ||
4 | * the format everytime you do something with a date. | ||
5 | */ | ||
6 | /** @ignore */ | ||
7 | Date.parseFunctions = {count:0}; | ||
8 | /** @ignore */ | ||
9 | Date.parseRegexes = []; | ||
10 | /** @ignore */ | ||
11 | Date.formatFunctions = {count:0}; | ||
12 | |||
13 | /** | ||
14 | * Formats a date given to the supplied format - the format syntax is the same as <a href="http://www.php.net/date">PHP's date() function</a>. | ||
15 | */ | ||
16 | Date.prototype.dateFormat = function(format) { | ||
17 | if (Date.formatFunctions[format] == null) { | ||
18 | Date.createNewFormat(format); | ||
19 | } | ||
20 | var func = Date.formatFunctions[format]; | ||
21 | return this[func](); | ||
22 | }; | ||
23 | |||
24 | /** | ||
25 | * Same as {@link #dateFormat} | ||
26 | */ | ||
27 | Date.prototype.format = Date.prototype.dateFormat; | ||
28 | |||
29 | /** @ignore */ | ||
30 | Date.createNewFormat = function(format) { | ||
31 | var funcName = "format" + Date.formatFunctions.count++; | ||
32 | Date.formatFunctions[format] = funcName; | ||
33 | var code = "Date.prototype." + funcName + " = function(){return "; | ||
34 | var special = false; | ||
35 | var ch = ''; | ||
36 | for (var i = 0; i < format.length; ++i) { | ||
37 | ch = format.charAt(i); | ||
38 | if (!special && ch == "\\") { | ||
39 | special = true; | ||
40 | } | ||
41 | else if (special) { | ||
42 | special = false; | ||
43 | code += "'" + String.escape(ch) + "' + "; | ||
44 | } | ||
45 | else { | ||
46 | code += Date.getFormatCode(ch); | ||
47 | } | ||
48 | } | ||
49 | eval(code.substring(0, code.length - 3) + ";}"); | ||
50 | }; | ||
51 | |||
52 | /** @ignore */ | ||
53 | Date.getFormatCode = function(character) { | ||
54 | switch (character) { | ||
55 | case "d": | ||
56 | return "String.leftPad(this.getDate(), 2, '0') + "; | ||
57 | case "D": | ||
58 | return "Date.dayNames[this.getDay()].substring(0, 3) + "; | ||
59 | case "j": | ||
60 | return "this.getDate() + "; | ||
61 | case "l": | ||
62 | return "Date.dayNames[this.getDay()] + "; | ||
63 | case "S": | ||
64 | return "this.getSuffix() + "; | ||
65 | case "w": | ||
66 | return "this.getDay() + "; | ||
67 | case "z": | ||
68 | return "this.getDayOfYear() + "; | ||
69 | case "W": | ||
70 | return "this.getWeekOfYear() + "; | ||
71 | case "F": | ||
72 | return "Date.monthNames[this.getMonth()] + "; | ||
73 | case "m": | ||
74 | return "String.leftPad(this.getMonth() + 1, 2, '0') + "; | ||
75 | case "M": | ||
76 | return "Date.monthNames[this.getMonth()].substring(0, 3) + "; | ||
77 | case "n": | ||
78 | return "(this.getMonth() + 1) + "; | ||
79 | case "t": | ||
80 | return "this.getDaysInMonth() + "; | ||
81 | case "L": | ||
82 | return "(this.isLeapYear() ? 1 : 0) + "; | ||
83 | case "Y": | ||
84 | return "this.getFullYear() + "; | ||
85 | case "y": | ||
86 | return "('' + this.getFullYear()).substring(2, 4) + "; | ||
87 | case "a": | ||
88 | return "(this.getHours() < 12 ? 'am' : 'pm') + "; | ||
89 | case "A": | ||
90 | return "(this.getHours() < 12 ? 'AM' : 'PM') + "; | ||
91 | case "g": | ||
92 | return "((this.getHours() %12) ? this.getHours() % 12 : 12) + "; | ||
93 | case "G": | ||
94 | return "this.getHours() + "; | ||
95 | case "h": | ||
96 | return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + "; | ||
97 | case "H": | ||
98 | return "String.leftPad(this.getHours(), 2, '0') + "; | ||
99 | case "i": | ||
100 | return "String.leftPad(this.getMinutes(), 2, '0') + "; | ||
101 | case "s": | ||
102 | return "String.leftPad(this.getSeconds(), 2, '0') + "; | ||
103 | case "O": | ||
104 | return "this.getGMTOffset() + "; | ||
105 | case "T": | ||
106 | return "this.getTimezone() + "; | ||
107 | case "Z": | ||
108 | return "(this.getTimezoneOffset() * -60) + "; | ||
109 | default: | ||
110 | return "'" + String.escape(character) + "' + "; | ||
111 | }; | ||
112 | }; | ||
113 | |||
114 | /** | ||
115 | * Parses a date given the supplied format - the format syntax is the same as <a href="http://www.php.net/date">PHP's date() function</a>. | ||
116 | */ | ||
117 | Date.parseDate = function(input, format) { | ||
118 | if (Date.parseFunctions[format] == null) { | ||
119 | Date.createParser(format); | ||
120 | } | ||
121 | var func = Date.parseFunctions[format]; | ||
122 | return Date[func](input); | ||
123 | }; | ||
124 | |||
125 | /** @ignore */ | ||
126 | Date.createParser = function(format) { | ||
127 | var funcName = "parse" + Date.parseFunctions.count++; | ||
128 | var regexNum = Date.parseRegexes.length; | ||
129 | var currentGroup = 1; | ||
130 | Date.parseFunctions[format] = funcName; | ||
131 | |||
132 | var code = "Date." + funcName + " = function(input){\n" | ||
133 | + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n" | ||
134 | + "var d = new Date();\n" | ||
135 | + "y = d.getFullYear();\n" | ||
136 | + "m = d.getMonth();\n" | ||
137 | + "d = d.getDate();\n" | ||
138 | + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n" | ||
139 | + "if (results && results.length > 0) {" | ||
140 | var regex = ""; | ||
141 | |||
142 | var special = false; | ||
143 | var ch = ''; | ||
144 | for (var i = 0; i < format.length; ++i) { | ||
145 | ch = format.charAt(i); | ||
146 | if (!special && ch == "\\") { | ||
147 | special = true; | ||
148 | } | ||
149 | else if (special) { | ||
150 | special = false; | ||
151 | regex += String.escape(ch); | ||
152 | } | ||
153 | else { | ||
154 | obj = Date.formatCodeToRegex(ch, currentGroup); | ||
155 | currentGroup += obj.g; | ||
156 | regex += obj.s; | ||
157 | if (obj.g && obj.c) { | ||
158 | code += obj.c; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n" | ||
164 | + "{return new Date(y, m, d, h, i, s);}\n" | ||
165 | + "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n" | ||
166 | + "{return new Date(y, m, d, h, i);}\n" | ||
167 | + "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n" | ||
168 | + "{return new Date(y, m, d, h);}\n" | ||
169 | + "else if (y > 0 && m >= 0 && d > 0)\n" | ||
170 | + "{return new Date(y, m, d);}\n" | ||
171 | + "else if (y > 0 && m >= 0)\n" | ||
172 | + "{return new Date(y, m);}\n" | ||
173 | + "else if (y > 0)\n" | ||
174 | + "{return new Date(y);}\n" | ||
175 | + "}return null;}"; | ||
176 | |||
177 | Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$"); | ||
178 | eval(code); | ||
179 | }; | ||
180 | |||
181 | /** @ignore */ | ||
182 | Date.formatCodeToRegex = function(character, currentGroup) { | ||
183 | switch (character) { | ||
184 | case "D": | ||
185 | return {g:0, | ||
186 | c:null, | ||
187 | s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"}; | ||
188 | case "j": | ||
189 | case "d": | ||
190 | return {g:1, | ||
191 | c:"d = parseInt(results[" + currentGroup + "], 10);\n", | ||
192 | s:"(\\d{1,2})"}; | ||
193 | case "l": | ||
194 | return {g:0, | ||
195 | c:null, | ||
196 | s:"(?:" + Date.dayNames.join("|") + ")"}; | ||
197 | case "S": | ||
198 | return {g:0, | ||
199 | c:null, | ||
200 | s:"(?:st|nd|rd|th)"}; | ||
201 | case "w": | ||
202 | return {g:0, | ||
203 | c:null, | ||
204 | s:"\\d"}; | ||
205 | case "z": | ||
206 | return {g:0, | ||
207 | c:null, | ||
208 | s:"(?:\\d{1,3})"}; | ||
209 | case "W": | ||
210 | return {g:0, | ||
211 | c:null, | ||
212 | s:"(?:\\d{2})"}; | ||
213 | case "F": | ||
214 | return {g:1, | ||
215 | c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n", | ||
216 | s:"(" + Date.monthNames.join("|") + ")"}; | ||
217 | case "M": | ||
218 | return {g:1, | ||
219 | c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n", | ||
220 | s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"}; | ||
221 | case "n": | ||
222 | case "m": | ||
223 | return {g:1, | ||
224 | c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n", | ||
225 | s:"(\\d{1,2})"}; | ||
226 | case "t": | ||
227 | return {g:0, | ||
228 | c:null, | ||
229 | s:"\\d{1,2}"}; | ||
230 | case "L": | ||
231 | return {g:0, | ||
232 | c:null, | ||
233 | s:"(?:1|0)"}; | ||
234 | case "Y": | ||
235 | return {g:1, | ||
236 | c:"y = parseInt(results[" + currentGroup + "], 10);\n", | ||
237 | s:"(\\d{4})"}; | ||
238 | case "y": | ||
239 | return {g:1, | ||
240 | c:"var ty = parseInt(results[" + currentGroup + "], 10);\n" | ||
241 | + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", | ||
242 | s:"(\\d{1,2})"}; | ||
243 | case "a": | ||
244 | return {g:1, | ||
245 | c:"if (results[" + currentGroup + "] == 'am') {\n" | ||
246 | + "if (h == 12) { h = 0; }\n" | ||
247 | + "} else { if (h < 12) { h += 12; }}", | ||
248 | s:"(am|pm)"}; | ||
249 | case "A": | ||
250 | return {g:1, | ||
251 | c:"if (results[" + currentGroup + "] == 'AM') {\n" | ||
252 | + "if (h == 12) { h = 0; }\n" | ||
253 | + "} else { if (h < 12) { h += 12; }}", | ||
254 | s:"(AM|PM)"}; | ||
255 | case "g": | ||
256 | case "G": | ||
257 | case "h": | ||
258 | case "H": | ||
259 | return {g:1, | ||
260 | c:"h = parseInt(results[" + currentGroup + "], 10);\n", | ||
261 | s:"(\\d{1,2})"}; | ||
262 | case "i": | ||
263 | return {g:1, | ||
264 | c:"i = parseInt(results[" + currentGroup + "], 10);\n", | ||
265 | s:"(\\d{2})"}; | ||
266 | case "s": | ||
267 | return {g:1, | ||
268 | c:"s = parseInt(results[" + currentGroup + "], 10);\n", | ||
269 | s:"(\\d{2})"}; | ||
270 | case "O": | ||
271 | return {g:0, | ||
272 | c:null, | ||
273 | s:"[+-]\\d{4}"}; | ||
274 | case "T": | ||
275 | return {g:0, | ||
276 | c:null, | ||
277 | s:"[A-Z]{3}"}; | ||
278 | case "Z": | ||
279 | return {g:0, | ||
280 | c:null, | ||
281 | s:"[+-]\\d{1,5}"}; | ||
282 | default: | ||
283 | return {g:0, | ||
284 | c:null, | ||
285 | s:String.escape(character)}; | ||
286 | } | ||
287 | }; | ||
288 | |||
289 | Date.prototype.getTimezone = function() { | ||
290 | return this.toString().replace( | ||
291 | /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace( | ||
292 | /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3"); | ||
293 | }; | ||
294 | |||
295 | Date.prototype.getGMTOffset = function() { | ||
296 | return (this.getTimezoneOffset() > 0 ? "-" : "+") | ||
297 | + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0") | ||
298 | + String.leftPad(this.getTimezoneOffset() % 60, 2, "0"); | ||
299 | }; | ||
300 | |||
301 | Date.prototype.getDayOfYear = function() { | ||
302 | var num = 0; | ||
303 | Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; | ||
304 | for (var i = 0; i < this.getMonth(); ++i) { | ||
305 | num += Date.daysInMonth[i]; | ||
306 | } | ||
307 | return num + this.getDate() - 1; | ||
308 | }; | ||
309 | |||
310 | Date.prototype.getWeekOfYear = function() { | ||
311 | // Skip to Thursday of this week | ||
312 | var now = this.getDayOfYear() + (4 - this.getDay()); | ||
313 | // Find the first Thursday of the year | ||
314 | var jan1 = new Date(this.getFullYear(), 0, 1); | ||
315 | var then = (7 - jan1.getDay() + 4); | ||
316 | return String.leftPad(((now - then) / 7) + 1, 2, "0"); | ||
317 | }; | ||
318 | |||
319 | Date.prototype.isLeapYear = function() { | ||
320 | var year = this.getFullYear(); | ||
321 | return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year))); | ||
322 | }; | ||
323 | |||
324 | Date.prototype.getFirstDayOfMonth = function() { | ||
325 | var day = (this.getDay() - (this.getDate() - 1)) % 7; | ||
326 | return (day < 0) ? (day + 7) : day; | ||
327 | }; | ||
328 | |||
329 | Date.prototype.getLastDayOfMonth = function() { | ||
330 | var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7; | ||
331 | return (day < 0) ? (day + 7) : day; | ||
332 | }; | ||
333 | |||
334 | Date.prototype.getDaysInMonth = function() { | ||
335 | Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28; | ||
336 | return Date.daysInMonth[this.getMonth()]; | ||
337 | }; | ||
338 | |||
339 | /** @ignore */ | ||
340 | Date.prototype.getSuffix = function() { | ||
341 | switch (this.getDate()) { | ||
342 | case 1: | ||
343 | case 21: | ||
344 | case 31: | ||
345 | return "st"; | ||
346 | case 2: | ||
347 | case 22: | ||
348 | return "nd"; | ||
349 | case 3: | ||
350 | case 23: | ||
351 | return "rd"; | ||
352 | default: | ||
353 | return "th"; | ||
354 | } | ||
355 | }; | ||
356 | |||
357 | /** @ignore */ | ||
358 | Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31]; | ||
359 | |||
360 | /** | ||
361 | * Override these values for international dates, for example... | ||
362 | * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...]; | ||
363 | */ | ||
364 | Date.monthNames = | ||
365 | ["January", | ||
366 | "February", | ||
367 | "March", | ||
368 | "April", | ||
369 | "May", | ||
370 | "June", | ||
371 | "July", | ||
372 | "August", | ||
373 | "September", | ||
374 | "October", | ||
375 | "November", | ||
376 | "December"]; | ||
377 | |||
378 | /** | ||
379 | * Override these values for international dates, for example... | ||
380 | * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...]; | ||
381 | */ | ||
382 | Date.dayNames = | ||
383 | ["Sunday", | ||
384 | "Monday", | ||
385 | "Tuesday", | ||
386 | "Wednesday", | ||
387 | "Thursday", | ||
388 | "Friday", | ||
389 | "Saturday"]; | ||
390 | |||
391 | /** @ignore */ | ||
392 | Date.y2kYear = 50; | ||
393 | |||
394 | /** @ignore */ | ||
395 | Date.monthNumbers = { | ||
396 | Jan:0, | ||
397 | Feb:1, | ||
398 | Mar:2, | ||
399 | Apr:3, | ||
400 | May:4, | ||
401 | Jun:5, | ||
402 | Jul:6, | ||
403 | Aug:7, | ||
404 | Sep:8, | ||
405 | Oct:9, | ||
406 | Nov:10, | ||
407 | Dec:11}; | ||