1 | |
---|
2 | /** |
---|
3 | * @fileOverview Date parsing and formatting operations without extending the Date built-in object. |
---|
4 | * @author Chris Leonello |
---|
5 | * @version #VERSION# |
---|
6 | * @date #DATE# |
---|
7 | */ |
---|
8 | |
---|
9 | (function($) { |
---|
10 | |
---|
11 | /** |
---|
12 | * @description |
---|
13 | * <p>Object with extended date parsing and formatting capabilities. |
---|
14 | * This library borrows many concepts and ideas from the Date Instance |
---|
15 | * Methods by Ken Snyder along with some parts of Ken's actual code.</p> |
---|
16 | * |
---|
17 | * <p>jsDate takes a different approach by not extending the built-in |
---|
18 | * Date Object, improving date parsing, allowing for multiple formatting |
---|
19 | * syntaxes and multiple and more easily expandable localization.</p> |
---|
20 | * |
---|
21 | * @author Chris Leonello |
---|
22 | * @date #date# |
---|
23 | * @version #VERSION# |
---|
24 | * @copyright (c) 2010 Chris Leonello |
---|
25 | * jsDate is currently available for use in all personal or commercial projects |
---|
26 | * under both the MIT and GPL version 2.0 licenses. This means that you can |
---|
27 | * choose the license that best suits your project and use it accordingly. |
---|
28 | * |
---|
29 | * <p>Ken's origianl Date Instance Methods and copyright notice:</p> |
---|
30 | * <pre> |
---|
31 | * Ken Snyder (ken d snyder at gmail dot com) |
---|
32 | * 2008-09-10 |
---|
33 | * version 2.0.2 (http://kendsnyder.com/sandbox/date/) |
---|
34 | * Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/) |
---|
35 | * </pre> |
---|
36 | * |
---|
37 | * @class |
---|
38 | * @name jsDate |
---|
39 | * @param {String | Number | Array | Date Object | Options Object} arguments Optional arguments, either a parsable date/time string, |
---|
40 | * a JavaScript timestamp, an array of numbers of form [year, month, day, hours, minutes, seconds, milliseconds], |
---|
41 | * a Date object, or an options object of form {syntax: "perl", date:some Date} where all options are optional. |
---|
42 | */ |
---|
43 | |
---|
44 | var jsDate = function () { |
---|
45 | |
---|
46 | this.syntax = jsDate.config.syntax; |
---|
47 | this._type = "jsDate"; |
---|
48 | this.utcOffset = new Date().getTimezoneOffset * 60000; |
---|
49 | this.proxy = new Date(); |
---|
50 | this.options = {}; |
---|
51 | this.locale = jsDate.regional.getLocale(); |
---|
52 | this.formatString = ''; |
---|
53 | this.defaultCentury = jsDate.config.defaultCentury; |
---|
54 | |
---|
55 | switch ( arguments.length ) { |
---|
56 | case 0: |
---|
57 | break; |
---|
58 | case 1: |
---|
59 | // other objects either won't have a _type property or, |
---|
60 | // if they do, it shouldn't be set to "jsDate", so |
---|
61 | // assume it is an options argument. |
---|
62 | if (get_type(arguments[0]) == "[object Object]" && arguments[0]._type != "jsDate") { |
---|
63 | var opts = this.options = arguments[0]; |
---|
64 | this.syntax = opts.syntax || this.syntax; |
---|
65 | this.defaultCentury = opts.defaultCentury || this.defaultCentury; |
---|
66 | this.proxy = jsDate.createDate(opts.date); |
---|
67 | } |
---|
68 | else { |
---|
69 | this.proxy = jsDate.createDate(arguments[0]); |
---|
70 | } |
---|
71 | break; |
---|
72 | default: |
---|
73 | var a = []; |
---|
74 | for ( var i=0; i<arguments.length; i++ ) { |
---|
75 | a.push(arguments[i]); |
---|
76 | } |
---|
77 | this.proxy = new Date( this.utcOffset ); |
---|
78 | this.proxy.setFullYear.apply( this.proxy, a.slice(0,3) ); |
---|
79 | if ( a.slice(3).length ) { |
---|
80 | this.proxy.setHours.apply( this.proxy, a.slice(3) ); |
---|
81 | } |
---|
82 | break; |
---|
83 | } |
---|
84 | }; |
---|
85 | |
---|
86 | /** |
---|
87 | * @namespace Configuration options that will be used as defaults for all instances on the page. |
---|
88 | * @property {String} defaultLocale The default locale to use [en]. |
---|
89 | * @property {String} syntax The default syntax to use [perl]. |
---|
90 | */ |
---|
91 | jsDate.config = { |
---|
92 | defaultLocale: 'en', |
---|
93 | syntax: 'perl', |
---|
94 | defaultCentury: 1900 |
---|
95 | }; |
---|
96 | |
---|
97 | /** |
---|
98 | * Add an arbitrary amount to the currently stored date |
---|
99 | * |
---|
100 | * @param {Number} number |
---|
101 | * @param {String} unit |
---|
102 | * @returns {jsDate} |
---|
103 | */ |
---|
104 | |
---|
105 | jsDate.prototype.add = function(number, unit) { |
---|
106 | var factor = multipliers[unit] || multipliers.day; |
---|
107 | if (typeof factor == 'number') { |
---|
108 | this.proxy.setTime(this.proxy.getTime() + (factor * number)); |
---|
109 | } else { |
---|
110 | factor.add(this, number); |
---|
111 | } |
---|
112 | return this; |
---|
113 | }; |
---|
114 | |
---|
115 | /** |
---|
116 | * Create a new jqplot.date object with the same date |
---|
117 | * |
---|
118 | * @returns {jsDate} |
---|
119 | */ |
---|
120 | |
---|
121 | jsDate.prototype.clone = function() { |
---|
122 | return new jsDate(this.proxy.getTime()); |
---|
123 | }; |
---|
124 | |
---|
125 | /** |
---|
126 | * Find the difference between this jsDate and another date. |
---|
127 | * |
---|
128 | * @param {String| Number| Array| jsDate Object| Date Object} dateObj |
---|
129 | * @param {String} unit |
---|
130 | * @param {Boolean} allowDecimal |
---|
131 | * @returns {Number} Number of units difference between dates. |
---|
132 | */ |
---|
133 | |
---|
134 | jsDate.prototype.diff = function(dateObj, unit, allowDecimal) { |
---|
135 | // ensure we have a Date object |
---|
136 | dateObj = new jsDate(dateObj); |
---|
137 | if (dateObj === null) { |
---|
138 | return null; |
---|
139 | } |
---|
140 | // get the multiplying factor integer or factor function |
---|
141 | var factor = multipliers[unit] || multipliers.day; |
---|
142 | if (typeof factor == 'number') { |
---|
143 | // multiply |
---|
144 | var unitDiff = (this.proxy.getTime() - dateObj.proxy.getTime()) / factor; |
---|
145 | } else { |
---|
146 | // run function |
---|
147 | var unitDiff = factor.diff(this.proxy, dateObj.proxy); |
---|
148 | } |
---|
149 | // if decimals are not allowed, round toward zero |
---|
150 | return (allowDecimal ? unitDiff : Math[unitDiff > 0 ? 'floor' : 'ceil'](unitDiff)); |
---|
151 | }; |
---|
152 | |
---|
153 | /** |
---|
154 | * Get the abbreviated name of the current week day |
---|
155 | * |
---|
156 | * @returns {String} |
---|
157 | */ |
---|
158 | |
---|
159 | jsDate.prototype.getAbbrDayName = function() { |
---|
160 | return jsDate.regional[this.locale]["dayNamesShort"][this.proxy.getDay()]; |
---|
161 | }; |
---|
162 | |
---|
163 | /** |
---|
164 | * Get the abbreviated name of the current month |
---|
165 | * |
---|
166 | * @returns {String} |
---|
167 | */ |
---|
168 | |
---|
169 | jsDate.prototype.getAbbrMonthName = function() { |
---|
170 | return jsDate.regional[this.locale]["monthNamesShort"][this.proxy.getMonth()]; |
---|
171 | }; |
---|
172 | |
---|
173 | /** |
---|
174 | * Get UPPER CASE AM or PM for the current time |
---|
175 | * |
---|
176 | * @returns {String} |
---|
177 | */ |
---|
178 | |
---|
179 | jsDate.prototype.getAMPM = function() { |
---|
180 | return this.proxy.getHours() >= 12 ? 'PM' : 'AM'; |
---|
181 | }; |
---|
182 | |
---|
183 | /** |
---|
184 | * Get lower case am or pm for the current time |
---|
185 | * |
---|
186 | * @returns {String} |
---|
187 | */ |
---|
188 | |
---|
189 | jsDate.prototype.getAmPm = function() { |
---|
190 | return this.proxy.getHours() >= 12 ? 'pm' : 'am'; |
---|
191 | }; |
---|
192 | |
---|
193 | /** |
---|
194 | * Get the century (19 for 20th Century) |
---|
195 | * |
---|
196 | * @returns {Integer} Century (19 for 20th century). |
---|
197 | */ |
---|
198 | jsDate.prototype.getCentury = function() { |
---|
199 | return parseInt(this.proxy.getFullYear()/100, 10); |
---|
200 | }; |
---|
201 | |
---|
202 | /** |
---|
203 | * Implements Date functionality |
---|
204 | */ |
---|
205 | jsDate.prototype.getDate = function() { |
---|
206 | return this.proxy.getDate(); |
---|
207 | }; |
---|
208 | |
---|
209 | /** |
---|
210 | * Implements Date functionality |
---|
211 | */ |
---|
212 | jsDate.prototype.getDay = function() { |
---|
213 | return this.proxy.getDay(); |
---|
214 | }; |
---|
215 | |
---|
216 | /** |
---|
217 | * Get the Day of week 1 (Monday) thru 7 (Sunday) |
---|
218 | * |
---|
219 | * @returns {Integer} Day of week 1 (Monday) thru 7 (Sunday) |
---|
220 | */ |
---|
221 | jsDate.prototype.getDayOfWeek = function() { |
---|
222 | var dow = this.proxy.getDay(); |
---|
223 | return dow===0?7:dow; |
---|
224 | }; |
---|
225 | |
---|
226 | /** |
---|
227 | * Get the day of the year |
---|
228 | * |
---|
229 | * @returns {Integer} 1 - 366, day of the year |
---|
230 | */ |
---|
231 | jsDate.prototype.getDayOfYear = function() { |
---|
232 | var d = this.proxy; |
---|
233 | var ms = d - new Date('' + d.getFullYear() + '/1/1 GMT'); |
---|
234 | ms += d.getTimezoneOffset()*60000; |
---|
235 | d = null; |
---|
236 | return parseInt(ms/60000/60/24, 10)+1; |
---|
237 | }; |
---|
238 | |
---|
239 | /** |
---|
240 | * Get the name of the current week day |
---|
241 | * |
---|
242 | * @returns {String} |
---|
243 | */ |
---|
244 | |
---|
245 | jsDate.prototype.getDayName = function() { |
---|
246 | return jsDate.regional[this.locale]["dayNames"][this.proxy.getDay()]; |
---|
247 | }; |
---|
248 | |
---|
249 | /** |
---|
250 | * Get the week number of the given year, starting with the first Sunday as the first week |
---|
251 | * @returns {Integer} Week number (13 for the 13th full week of the year). |
---|
252 | */ |
---|
253 | jsDate.prototype.getFullWeekOfYear = function() { |
---|
254 | var d = this.proxy; |
---|
255 | var doy = this.getDayOfYear(); |
---|
256 | var rdow = 6-d.getDay(); |
---|
257 | var woy = parseInt((doy+rdow)/7, 10); |
---|
258 | return woy; |
---|
259 | }; |
---|
260 | |
---|
261 | /** |
---|
262 | * Implements Date functionality |
---|
263 | */ |
---|
264 | jsDate.prototype.getFullYear = function() { |
---|
265 | return this.proxy.getFullYear(); |
---|
266 | }; |
---|
267 | |
---|
268 | /** |
---|
269 | * Get the GMT offset in hours and minutes (e.g. +06:30) |
---|
270 | * |
---|
271 | * @returns {String} |
---|
272 | */ |
---|
273 | |
---|
274 | jsDate.prototype.getGmtOffset = function() { |
---|
275 | // divide the minutes offset by 60 |
---|
276 | var hours = this.proxy.getTimezoneOffset() / 60; |
---|
277 | // decide if we are ahead of or behind GMT |
---|
278 | var prefix = hours < 0 ? '+' : '-'; |
---|
279 | // remove the negative sign if any |
---|
280 | hours = Math.abs(hours); |
---|
281 | // add the +/- to the padded number of hours to : to the padded minutes |
---|
282 | return prefix + addZeros(Math.floor(hours), 2) + ':' + addZeros((hours % 1) * 60, 2); |
---|
283 | }; |
---|
284 | |
---|
285 | /** |
---|
286 | * Implements Date functionality |
---|
287 | */ |
---|
288 | jsDate.prototype.getHours = function() { |
---|
289 | return this.proxy.getHours(); |
---|
290 | }; |
---|
291 | |
---|
292 | /** |
---|
293 | * Get the current hour on a 12-hour scheme |
---|
294 | * |
---|
295 | * @returns {Integer} |
---|
296 | */ |
---|
297 | |
---|
298 | jsDate.prototype.getHours12 = function() { |
---|
299 | var hours = this.proxy.getHours(); |
---|
300 | return hours > 12 ? hours - 12 : (hours == 0 ? 12 : hours); |
---|
301 | }; |
---|
302 | |
---|
303 | |
---|
304 | jsDate.prototype.getIsoWeek = function() { |
---|
305 | var d = this.proxy; |
---|
306 | var woy = d.getWeekOfYear(); |
---|
307 | var dow1_1 = (new Date('' + d.getFullYear() + '/1/1')).getDay(); |
---|
308 | // First week is 01 and not 00 as in the case of %U and %W, |
---|
309 | // so we add 1 to the final result except if day 1 of the year |
---|
310 | // is a Monday (then %W returns 01). |
---|
311 | // We also need to subtract 1 if the day 1 of the year is |
---|
312 | // Friday-Sunday, so the resulting equation becomes: |
---|
313 | var idow = woy + (dow1_1 > 4 || dow1_1 <= 1 ? 0 : 1); |
---|
314 | if(idow == 53 && (new Date('' + d.getFullYear() + '/12/31')).getDay() < 4) |
---|
315 | { |
---|
316 | idow = 1; |
---|
317 | } |
---|
318 | else if(idow === 0) |
---|
319 | { |
---|
320 | d = new jsDate(new Date('' + (d.getFullYear()-1) + '/12/31')); |
---|
321 | idow = d.getIsoWeek(); |
---|
322 | } |
---|
323 | d = null; |
---|
324 | return idow; |
---|
325 | }; |
---|
326 | |
---|
327 | /** |
---|
328 | * Implements Date functionality |
---|
329 | */ |
---|
330 | jsDate.prototype.getMilliseconds = function() { |
---|
331 | return this.proxy.getMilliseconds(); |
---|
332 | }; |
---|
333 | |
---|
334 | /** |
---|
335 | * Implements Date functionality |
---|
336 | */ |
---|
337 | jsDate.prototype.getMinutes = function() { |
---|
338 | return this.proxy.getMinutes(); |
---|
339 | }; |
---|
340 | |
---|
341 | /** |
---|
342 | * Implements Date functionality |
---|
343 | */ |
---|
344 | jsDate.prototype.getMonth = function() { |
---|
345 | return this.proxy.getMonth(); |
---|
346 | }; |
---|
347 | |
---|
348 | /** |
---|
349 | * Get the name of the current month |
---|
350 | * |
---|
351 | * @returns {String} |
---|
352 | */ |
---|
353 | |
---|
354 | jsDate.prototype.getMonthName = function() { |
---|
355 | return jsDate.regional[this.locale]["monthNames"][this.proxy.getMonth()]; |
---|
356 | }; |
---|
357 | |
---|
358 | /** |
---|
359 | * Get the number of the current month, 1-12 |
---|
360 | * |
---|
361 | * @returns {Integer} |
---|
362 | */ |
---|
363 | |
---|
364 | jsDate.prototype.getMonthNumber = function() { |
---|
365 | return this.proxy.getMonth() + 1; |
---|
366 | }; |
---|
367 | |
---|
368 | /** |
---|
369 | * Implements Date functionality |
---|
370 | */ |
---|
371 | jsDate.prototype.getSeconds = function() { |
---|
372 | return this.proxy.getSeconds(); |
---|
373 | }; |
---|
374 | |
---|
375 | /** |
---|
376 | * Return a proper two-digit year integer |
---|
377 | * |
---|
378 | * @returns {Integer} |
---|
379 | */ |
---|
380 | |
---|
381 | jsDate.prototype.getShortYear = function() { |
---|
382 | return this.proxy.getYear() % 100; |
---|
383 | }; |
---|
384 | |
---|
385 | /** |
---|
386 | * Implements Date functionality |
---|
387 | */ |
---|
388 | jsDate.prototype.getTime = function() { |
---|
389 | return this.proxy.getTime(); |
---|
390 | }; |
---|
391 | |
---|
392 | /** |
---|
393 | * Get the timezone abbreviation |
---|
394 | * |
---|
395 | * @returns {String} Abbreviation for the timezone |
---|
396 | */ |
---|
397 | jsDate.prototype.getTimezoneAbbr = function() { |
---|
398 | return this.proxy.toString().replace(/^.*\(([^)]+)\)$/, '$1'); |
---|
399 | }; |
---|
400 | |
---|
401 | /** |
---|
402 | * Get the browser-reported name for the current timezone (e.g. MDT, Mountain Daylight Time) |
---|
403 | * |
---|
404 | * @returns {String} |
---|
405 | */ |
---|
406 | jsDate.prototype.getTimezoneName = function() { |
---|
407 | var match = /(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString()); |
---|
408 | return match[1] || match[2] || 'GMT' + this.getGmtOffset(); |
---|
409 | }; |
---|
410 | |
---|
411 | /** |
---|
412 | * Implements Date functionality |
---|
413 | */ |
---|
414 | jsDate.prototype.getTimezoneOffset = function() { |
---|
415 | return this.proxy.getTimezoneOffset(); |
---|
416 | }; |
---|
417 | |
---|
418 | |
---|
419 | /** |
---|
420 | * Get the week number of the given year, starting with the first Monday as the first week |
---|
421 | * @returns {Integer} Week number (13 for the 13th week of the year). |
---|
422 | */ |
---|
423 | jsDate.prototype.getWeekOfYear = function() { |
---|
424 | var doy = this.getDayOfYear(); |
---|
425 | var rdow = 7 - this.getDayOfWeek(); |
---|
426 | var woy = parseInt((doy+rdow)/7, 10); |
---|
427 | return woy; |
---|
428 | }; |
---|
429 | |
---|
430 | /** |
---|
431 | * Get the current date as a Unix timestamp |
---|
432 | * |
---|
433 | * @returns {Integer} |
---|
434 | */ |
---|
435 | |
---|
436 | jsDate.prototype.getUnix = function() { |
---|
437 | return Math.round(this.proxy.getTime() / 1000, 0); |
---|
438 | }; |
---|
439 | |
---|
440 | /** |
---|
441 | * Implements Date functionality |
---|
442 | */ |
---|
443 | jsDate.prototype.getYear = function() { |
---|
444 | return this.proxy.getYear(); |
---|
445 | }; |
---|
446 | |
---|
447 | /** |
---|
448 | * Return a date one day ahead (or any other unit) |
---|
449 | * |
---|
450 | * @param {String} unit Optional, year | month | day | week | hour | minute | second | millisecond |
---|
451 | * @returns {jsDate} |
---|
452 | */ |
---|
453 | |
---|
454 | jsDate.prototype.next = function(unit) { |
---|
455 | unit = unit || 'day'; |
---|
456 | return this.clone().add(1, unit); |
---|
457 | }; |
---|
458 | |
---|
459 | /** |
---|
460 | * Set the jsDate instance to a new date. |
---|
461 | * |
---|
462 | * @param {String | Number | Array | Date Object | jsDate Object | Options Object} arguments Optional arguments, |
---|
463 | * either a parsable date/time string, |
---|
464 | * a JavaScript timestamp, an array of numbers of form [year, month, day, hours, minutes, seconds, milliseconds], |
---|
465 | * a Date object, jsDate Object or an options object of form {syntax: "perl", date:some Date} where all options are optional. |
---|
466 | */ |
---|
467 | jsDate.prototype.set = function() { |
---|
468 | switch ( arguments.length ) { |
---|
469 | case 0: |
---|
470 | this.proxy = new Date(); |
---|
471 | break; |
---|
472 | case 1: |
---|
473 | // other objects either won't have a _type property or, |
---|
474 | // if they do, it shouldn't be set to "jsDate", so |
---|
475 | // assume it is an options argument. |
---|
476 | if (get_type(arguments[0]) == "[object Object]" && arguments[0]._type != "jsDate") { |
---|
477 | var opts = this.options = arguments[0]; |
---|
478 | this.syntax = opts.syntax || this.syntax; |
---|
479 | this.defaultCentury = opts.defaultCentury || this.defaultCentury; |
---|
480 | this.proxy = jsDate.createDate(opts.date); |
---|
481 | } |
---|
482 | else { |
---|
483 | this.proxy = jsDate.createDate(arguments[0]); |
---|
484 | } |
---|
485 | break; |
---|
486 | default: |
---|
487 | var a = []; |
---|
488 | for ( var i=0; i<arguments.length; i++ ) { |
---|
489 | a.push(arguments[i]); |
---|
490 | } |
---|
491 | this.proxy = new Date( this.utcOffset ); |
---|
492 | this.proxy.setFullYear.apply( this.proxy, a.slice(0,3) ); |
---|
493 | if ( a.slice(3).length ) { |
---|
494 | this.proxy.setHours.apply( this.proxy, a.slice(3) ); |
---|
495 | } |
---|
496 | break; |
---|
497 | } |
---|
498 | }; |
---|
499 | |
---|
500 | /** |
---|
501 | * Sets the day of the month for a specified date according to local time. |
---|
502 | * @param {Integer} dayValue An integer from 1 to 31, representing the day of the month. |
---|
503 | */ |
---|
504 | jsDate.prototype.setDate = function(n) { |
---|
505 | return this.proxy.setDate(n); |
---|
506 | }; |
---|
507 | |
---|
508 | /** |
---|
509 | * Sets the full year for a specified date according to local time. |
---|
510 | * @param {Integer} yearValue The numeric value of the year, for example, 1995. |
---|
511 | * @param {Integer} monthValue Optional, between 0 and 11 representing the months January through December. |
---|
512 | * @param {Integer} dayValue Optional, between 1 and 31 representing the day of the month. If you specify the dayValue parameter, you must also specify the monthValue. |
---|
513 | */ |
---|
514 | jsDate.prototype.setFullYear = function() { |
---|
515 | return this.proxy.setFullYear.apply(this.proxy, arguments); |
---|
516 | }; |
---|
517 | |
---|
518 | /** |
---|
519 | * Sets the hours for a specified date according to local time. |
---|
520 | * |
---|
521 | * @param {Integer} hoursValue An integer between 0 and 23, representing the hour. |
---|
522 | * @param {Integer} minutesValue Optional, An integer between 0 and 59, representing the minutes. |
---|
523 | * @param {Integer} secondsValue Optional, An integer between 0 and 59, representing the seconds. |
---|
524 | * If you specify the secondsValue parameter, you must also specify the minutesValue. |
---|
525 | * @param {Integer} msValue Optional, A number between 0 and 999, representing the milliseconds. |
---|
526 | * If you specify the msValue parameter, you must also specify the minutesValue and secondsValue. |
---|
527 | */ |
---|
528 | jsDate.prototype.setHours = function() { |
---|
529 | return this.proxy.setHours.apply(this.proxy, arguments); |
---|
530 | }; |
---|
531 | |
---|
532 | /** |
---|
533 | * Implements Date functionality |
---|
534 | */ |
---|
535 | jsDate.prototype.setMilliseconds = function(n) { |
---|
536 | return this.proxy.setMilliseconds(n); |
---|
537 | }; |
---|
538 | |
---|
539 | /** |
---|
540 | * Implements Date functionality |
---|
541 | */ |
---|
542 | jsDate.prototype.setMinutes = function() { |
---|
543 | return this.proxy.setMinutes.apply(this.proxy, arguments); |
---|
544 | }; |
---|
545 | |
---|
546 | /** |
---|
547 | * Implements Date functionality |
---|
548 | */ |
---|
549 | jsDate.prototype.setMonth = function() { |
---|
550 | return this.proxy.setMonth.apply(this.proxy, arguments); |
---|
551 | }; |
---|
552 | |
---|
553 | /** |
---|
554 | * Implements Date functionality |
---|
555 | */ |
---|
556 | jsDate.prototype.setSeconds = function() { |
---|
557 | return this.proxy.setSeconds.apply(this.proxy, arguments); |
---|
558 | }; |
---|
559 | |
---|
560 | /** |
---|
561 | * Implements Date functionality |
---|
562 | */ |
---|
563 | jsDate.prototype.setTime = function(n) { |
---|
564 | return this.proxy.setTime(n); |
---|
565 | }; |
---|
566 | |
---|
567 | /** |
---|
568 | * Implements Date functionality |
---|
569 | */ |
---|
570 | jsDate.prototype.setYear = function() { |
---|
571 | return this.proxy.setYear.apply(this.proxy, arguments); |
---|
572 | }; |
---|
573 | |
---|
574 | /** |
---|
575 | * Provide a formatted string representation of this date. |
---|
576 | * |
---|
577 | * @param {String} formatString A format string. |
---|
578 | * See: {@link jsDate.formats}. |
---|
579 | * @returns {String} Date String. |
---|
580 | */ |
---|
581 | |
---|
582 | jsDate.prototype.strftime = function(formatString) { |
---|
583 | formatString = formatString || this.formatString || jsDate.regional[this.locale]['formatString']; |
---|
584 | return jsDate.strftime(this, formatString, this.syntax); |
---|
585 | }; |
---|
586 | |
---|
587 | /** |
---|
588 | * Return a String representation of this jsDate object. |
---|
589 | * @returns {String} Date string. |
---|
590 | */ |
---|
591 | |
---|
592 | jsDate.prototype.toString = function() { |
---|
593 | return this.proxy.toString(); |
---|
594 | }; |
---|
595 | |
---|
596 | /** |
---|
597 | * Convert the current date to an 8-digit integer (%Y%m%d) |
---|
598 | * |
---|
599 | * @returns {Integer} |
---|
600 | */ |
---|
601 | |
---|
602 | jsDate.prototype.toYmdInt = function() { |
---|
603 | return (this.proxy.getFullYear() * 10000) + (this.getMonthNumber() * 100) + this.proxy.getDate(); |
---|
604 | }; |
---|
605 | |
---|
606 | /** |
---|
607 | * @namespace Holds localizations for month/day names. |
---|
608 | * <p>jsDate attempts to detect locale when loaded and defaults to 'en'. |
---|
609 | * If a localization is detected which is not available, jsDate defaults to 'en'. |
---|
610 | * Additional localizations can be added after jsDate loads. After adding a localization, |
---|
611 | * call the jsDate.regional.getLocale() method. Currently, en, fr and de are defined.</p> |
---|
612 | * |
---|
613 | * <p>Localizations must be an object and have the following properties defined: monthNames, monthNamesShort, dayNames, dayNamesShort and Localizations are added like:</p> |
---|
614 | * <pre class="code"> |
---|
615 | * jsDate.regional['en'] = { |
---|
616 | * monthNames : 'January February March April May June July August September October November December'.split(' '), |
---|
617 | * monthNamesShort : 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '), |
---|
618 | * dayNames : 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split(' '), |
---|
619 | * dayNamesShort : 'Sun Mon Tue Wed Thu Fri Sat'.split(' ') |
---|
620 | * }; |
---|
621 | * </pre> |
---|
622 | * <p>After adding localizations, call <code>jsDate.regional.getLocale();</code> to update the locale setting with the |
---|
623 | * new localizations.</p> |
---|
624 | */ |
---|
625 | |
---|
626 | jsDate.regional = { |
---|
627 | 'en': { |
---|
628 | monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'], |
---|
629 | monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun','Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], |
---|
630 | dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], |
---|
631 | dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], |
---|
632 | formatString: '%Y-%m-%d %H:%M:%S' |
---|
633 | }, |
---|
634 | |
---|
635 | 'fr': { |
---|
636 | monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'], |
---|
637 | monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun','Jul','Aoû','Sep','Oct','Nov','Déc'], |
---|
638 | dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'], |
---|
639 | dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'], |
---|
640 | formatString: '%Y-%m-%d %H:%M:%S' |
---|
641 | }, |
---|
642 | |
---|
643 | 'de': { |
---|
644 | monthNames: ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'], |
---|
645 | monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'], |
---|
646 | dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'], |
---|
647 | dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'], |
---|
648 | formatString: '%Y-%m-%d %H:%M:%S' |
---|
649 | }, |
---|
650 | |
---|
651 | 'es': { |
---|
652 | monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'], |
---|
653 | monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun', 'Jul','Ago','Sep','Oct','Nov','Dic'], |
---|
654 | dayNames: ['Domingo','Lunes','Martes','Miércoles','Jueves','Viernes','Sábado'], |
---|
655 | dayNamesShort: ['Dom','Lun','Mar','Mié','Juv','Vie','Sáb'], |
---|
656 | formatString: '%Y-%m-%d %H:%M:%S' |
---|
657 | }, |
---|
658 | |
---|
659 | 'ru': { |
---|
660 | monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'], |
---|
661 | monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн','Июл','Авг','Сен','Окт','Ноя','Дек'], |
---|
662 | dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'], |
---|
663 | dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'], |
---|
664 | formatString: '%Y-%m-%d %H:%M:%S' |
---|
665 | }, |
---|
666 | |
---|
667 | 'ar': { |
---|
668 | monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'آذار', 'حزيران','تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], |
---|
669 | monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'], |
---|
670 | dayNames: ['السبت', 'الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'], |
---|
671 | dayNamesShort: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'], |
---|
672 | formatString: '%Y-%m-%d %H:%M:%S' |
---|
673 | }, |
---|
674 | |
---|
675 | 'pt': { |
---|
676 | monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho','Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'], |
---|
677 | monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'], |
---|
678 | dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'], |
---|
679 | dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'], |
---|
680 | formatString: '%Y-%m-%d %H:%M:%S' |
---|
681 | }, |
---|
682 | |
---|
683 | 'pt-BR': { |
---|
684 | monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho', 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'], |
---|
685 | monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'], |
---|
686 | dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'], |
---|
687 | dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'], |
---|
688 | formatString: '%Y-%m-%d %H:%M:%S' |
---|
689 | } |
---|
690 | |
---|
691 | |
---|
692 | }; |
---|
693 | |
---|
694 | // Set english variants to 'en' |
---|
695 | jsDate.regional['en-US'] = jsDate.regional['en-GB'] = jsDate.regional['en']; |
---|
696 | |
---|
697 | /** |
---|
698 | * Try to determine the users locale based on the lang attribute of the html page. Defaults to 'en' |
---|
699 | * if it cannot figure out a locale of if the locale does not have a localization defined. |
---|
700 | * @returns {String} locale |
---|
701 | */ |
---|
702 | |
---|
703 | jsDate.regional.getLocale = function () { |
---|
704 | var l = jsDate.config.defaultLocale; |
---|
705 | |
---|
706 | if ( document && document.getElementsByTagName('html') && document.getElementsByTagName('html')[0].lang ) { |
---|
707 | l = document.getElementsByTagName('html')[0].lang; |
---|
708 | if (!jsDate.regional.hasOwnProperty(l)) { |
---|
709 | l = jsDate.config.defaultLocale; |
---|
710 | } |
---|
711 | } |
---|
712 | |
---|
713 | return l; |
---|
714 | }; |
---|
715 | |
---|
716 | // ms in day |
---|
717 | var day = 24 * 60 * 60 * 1000; |
---|
718 | |
---|
719 | // padd a number with zeros |
---|
720 | var addZeros = function(num, digits) { |
---|
721 | num = String(num); |
---|
722 | var i = digits - num.length; |
---|
723 | var s = String(Math.pow(10, i)).slice(1); |
---|
724 | return s.concat(num); |
---|
725 | }; |
---|
726 | |
---|
727 | // representations used for calculating differences between dates. |
---|
728 | // This borrows heavily from Ken Snyder's work. |
---|
729 | var multipliers = { |
---|
730 | millisecond: 1, |
---|
731 | second: 1000, |
---|
732 | minute: 60 * 1000, |
---|
733 | hour: 60 * 60 * 1000, |
---|
734 | day: day, |
---|
735 | week: 7 * day, |
---|
736 | month: { |
---|
737 | // add a number of months |
---|
738 | add: function(d, number) { |
---|
739 | // add any years needed (increments of 12) |
---|
740 | multipliers.year.add(d, Math[number > 0 ? 'floor' : 'ceil'](number / 12)); |
---|
741 | // ensure that we properly wrap betwen December and January |
---|
742 | var prevMonth = d.getMonth() + (number % 12); |
---|
743 | if (prevMonth == 12) { |
---|
744 | prevMonth = 0; |
---|
745 | d.setYear(d.getFullYear() + 1); |
---|
746 | } else if (prevMonth == -1) { |
---|
747 | prevMonth = 11; |
---|
748 | d.setYear(d.getFullYear() - 1); |
---|
749 | } |
---|
750 | d.setMonth(prevMonth); |
---|
751 | }, |
---|
752 | // get the number of months between two Date objects (decimal to the nearest day) |
---|
753 | diff: function(d1, d2) { |
---|
754 | // get the number of years |
---|
755 | var diffYears = d1.getFullYear() - d2.getFullYear(); |
---|
756 | // get the number of remaining months |
---|
757 | var diffMonths = d1.getMonth() - d2.getMonth() + (diffYears * 12); |
---|
758 | // get the number of remaining days |
---|
759 | var diffDays = d1.getDate() - d2.getDate(); |
---|
760 | // return the month difference with the days difference as a decimal |
---|
761 | return diffMonths + (diffDays / 30); |
---|
762 | } |
---|
763 | }, |
---|
764 | year: { |
---|
765 | // add a number of years |
---|
766 | add: function(d, number) { |
---|
767 | d.setYear(d.getFullYear() + Math[number > 0 ? 'floor' : 'ceil'](number)); |
---|
768 | }, |
---|
769 | // get the number of years between two Date objects (decimal to the nearest day) |
---|
770 | diff: function(d1, d2) { |
---|
771 | return multipliers.month.diff(d1, d2) / 12; |
---|
772 | } |
---|
773 | } |
---|
774 | }; |
---|
775 | // |
---|
776 | // Alias each multiplier with an 's' to allow 'year' and 'years' for example. |
---|
777 | // This comes from Ken Snyders work. |
---|
778 | // |
---|
779 | for (var unit in multipliers) { |
---|
780 | if (unit.substring(unit.length - 1) != 's') { // IE will iterate newly added properties :| |
---|
781 | multipliers[unit + 's'] = multipliers[unit]; |
---|
782 | } |
---|
783 | } |
---|
784 | |
---|
785 | // |
---|
786 | // take a jsDate instance and a format code and return the formatted value. |
---|
787 | // This is a somewhat modified version of Ken Snyder's method. |
---|
788 | // |
---|
789 | var format = function(d, code, syntax) { |
---|
790 | // if shorcut codes are used, recursively expand those. |
---|
791 | if (jsDate.formats[syntax]["shortcuts"][code]) { |
---|
792 | return jsDate.strftime(d, jsDate.formats[syntax]["shortcuts"][code], syntax); |
---|
793 | } else { |
---|
794 | // get the format code function and addZeros() argument |
---|
795 | var getter = (jsDate.formats[syntax]["codes"][code] || '').split('.'); |
---|
796 | var nbr = d['get' + getter[0]] ? d['get' + getter[0]]() : ''; |
---|
797 | if (getter[1]) { |
---|
798 | nbr = addZeros(nbr, getter[1]); |
---|
799 | } |
---|
800 | return nbr; |
---|
801 | } |
---|
802 | }; |
---|
803 | |
---|
804 | /** |
---|
805 | * @static |
---|
806 | * Static function for convert a date to a string according to a given format. Also acts as namespace for strftime format codes. |
---|
807 | * <p>strftime formatting can be accomplished without creating a jsDate object by calling jsDate.strftime():</p> |
---|
808 | * <pre class="code"> |
---|
809 | * var formattedDate = jsDate.strftime('Feb 8, 2006 8:48:32', '%Y-%m-%d %H:%M:%S'); |
---|
810 | * </pre> |
---|
811 | * @param {String | Number | Array | jsDate Object | Date Object} date A parsable date string, JavaScript time stamp, Array of form [year, month, day, hours, minutes, seconds, milliseconds], jsDate Object or Date object. |
---|
812 | * @param {String} formatString String with embedded date formatting codes. |
---|
813 | * See: {@link jsDate.formats}. |
---|
814 | * @param {String} syntax Optional syntax to use [default perl]. |
---|
815 | * @param {String} locale Optional locale to use. |
---|
816 | * @returns {String} Formatted representation of the date. |
---|
817 | */ |
---|
818 | // |
---|
819 | // Logic as implemented here is very similar to Ken Snyder's Date Instance Methods. |
---|
820 | // |
---|
821 | jsDate.strftime = function(d, formatString, syntax, locale) { |
---|
822 | var syn = 'perl'; |
---|
823 | var loc = jsDate.regional.getLocale(); |
---|
824 | |
---|
825 | // check if syntax and locale are available or reversed |
---|
826 | if (syntax && jsDate.formats.hasOwnProperty(syntax)) { |
---|
827 | syn = syntax; |
---|
828 | } |
---|
829 | else if (syntax && jsDate.regional.hasOwnProperty(syntax)) { |
---|
830 | loc = syntax; |
---|
831 | } |
---|
832 | |
---|
833 | if (locale && jsDate.formats.hasOwnProperty(locale)) { |
---|
834 | syn = locale; |
---|
835 | } |
---|
836 | else if (locale && jsDate.regional.hasOwnProperty(locale)) { |
---|
837 | loc = locale; |
---|
838 | } |
---|
839 | |
---|
840 | if (get_type(d) != "[object Object]" || d._type != "jsDate") { |
---|
841 | d = new jsDate(d); |
---|
842 | d.locale = loc; |
---|
843 | } |
---|
844 | if (!formatString) { |
---|
845 | formatString = d.formatString || jsDate.regional[loc]['formatString']; |
---|
846 | } |
---|
847 | // default the format string to year-month-day |
---|
848 | var source = formatString || '%Y-%m-%d', |
---|
849 | result = '', |
---|
850 | match; |
---|
851 | // replace each format code |
---|
852 | while (source.length > 0) { |
---|
853 | if (match = source.match(jsDate.formats[syn].codes.matcher)) { |
---|
854 | result += source.slice(0, match.index); |
---|
855 | result += (match[1] || '') + format(d, match[2], syn); |
---|
856 | source = source.slice(match.index + match[0].length); |
---|
857 | } else { |
---|
858 | result += source; |
---|
859 | source = ''; |
---|
860 | } |
---|
861 | } |
---|
862 | return result; |
---|
863 | }; |
---|
864 | |
---|
865 | /** |
---|
866 | * @namespace |
---|
867 | * Namespace to hold format codes and format shortcuts. "perl" and "php" format codes |
---|
868 | * and shortcuts are defined by default. Additional codes and shortcuts can be |
---|
869 | * added like: |
---|
870 | * |
---|
871 | * <pre class="code"> |
---|
872 | * jsDate.formats["perl"] = { |
---|
873 | * "codes": { |
---|
874 | * matcher: /someregex/, |
---|
875 | * Y: "fullYear", // name of "get" method without the "get", |
---|
876 | * ..., // more codes |
---|
877 | * }, |
---|
878 | * "shortcuts": { |
---|
879 | * F: '%Y-%m-%d', |
---|
880 | * ..., // more shortcuts |
---|
881 | * } |
---|
882 | * }; |
---|
883 | * </pre> |
---|
884 | * |
---|
885 | * <p>Additionally, ISO and SQL shortcuts are defined and can be accesses via: |
---|
886 | * <code>jsDate.formats.ISO</code> and <code>jsDate.formats.SQL</code> |
---|
887 | */ |
---|
888 | |
---|
889 | jsDate.formats = { |
---|
890 | ISO:'%Y-%m-%dT%H:%M:%S.%N%G', |
---|
891 | SQL:'%Y-%m-%d %H:%M:%S' |
---|
892 | }; |
---|
893 | |
---|
894 | /** |
---|
895 | * Perl format codes and shortcuts for strftime. |
---|
896 | * |
---|
897 | * A hash (object) of codes where each code must be an array where the first member is |
---|
898 | * the name of a Date.prototype or jsDate.prototype function to call |
---|
899 | * and optionally a second member indicating the number to pass to addZeros() |
---|
900 | * |
---|
901 | * <p>The following format codes are defined:</p> |
---|
902 | * |
---|
903 | * <pre class="code"> |
---|
904 | * Code Result Description |
---|
905 | * == Years == |
---|
906 | * %Y 2008 Four-digit year |
---|
907 | * %y 08 Two-digit year |
---|
908 | * |
---|
909 | * == Months == |
---|
910 | * %m 09 Two-digit month |
---|
911 | * %#m 9 One or two-digit month |
---|
912 | * %B September Full month name |
---|
913 | * %b Sep Abbreviated month name |
---|
914 | * |
---|
915 | * == Days == |
---|
916 | * %d 05 Two-digit day of month |
---|
917 | * %#d 5 One or two-digit day of month |
---|
918 | * %e 5 One or two-digit day of month |
---|
919 | * %A Sunday Full name of the day of the week |
---|
920 | * %a Sun Abbreviated name of the day of the week |
---|
921 | * %w 0 Number of the day of the week (0 = Sunday, 6 = Saturday) |
---|
922 | * |
---|
923 | * == Hours == |
---|
924 | * %H 23 Hours in 24-hour format (two digits) |
---|
925 | * %#H 3 Hours in 24-hour integer format (one or two digits) |
---|
926 | * %I 11 Hours in 12-hour format (two digits) |
---|
927 | * %#I 3 Hours in 12-hour integer format (one or two digits) |
---|
928 | * %p PM AM or PM |
---|
929 | * |
---|
930 | * == Minutes == |
---|
931 | * %M 09 Minutes (two digits) |
---|
932 | * %#M 9 Minutes (one or two digits) |
---|
933 | * |
---|
934 | * == Seconds == |
---|
935 | * %S 02 Seconds (two digits) |
---|
936 | * %#S 2 Seconds (one or two digits) |
---|
937 | * %s 1206567625723 Unix timestamp (Seconds past 1970-01-01 00:00:00) |
---|
938 | * |
---|
939 | * == Milliseconds == |
---|
940 | * %N 008 Milliseconds (three digits) |
---|
941 | * %#N 8 Milliseconds (one to three digits) |
---|
942 | * |
---|
943 | * == Timezone == |
---|
944 | * %O 360 difference in minutes between local time and GMT |
---|
945 | * %Z Mountain Standard Time Name of timezone as reported by browser |
---|
946 | * %G 06:00 Hours and minutes between GMT |
---|
947 | * |
---|
948 | * == Shortcuts == |
---|
949 | * %F 2008-03-26 %Y-%m-%d |
---|
950 | * %T 05:06:30 %H:%M:%S |
---|
951 | * %X 05:06:30 %H:%M:%S |
---|
952 | * %x 03/26/08 %m/%d/%y |
---|
953 | * %D 03/26/08 %m/%d/%y |
---|
954 | * %#c Wed Mar 26 15:31:00 2008 %a %b %e %H:%M:%S %Y |
---|
955 | * %v 3-Sep-2008 %e-%b-%Y |
---|
956 | * %R 15:31 %H:%M |
---|
957 | * %r 03:31:00 PM %I:%M:%S %p |
---|
958 | * |
---|
959 | * == Characters == |
---|
960 | * %n \n Newline |
---|
961 | * %t \t Tab |
---|
962 | * %% % Percent Symbol |
---|
963 | * </pre> |
---|
964 | * |
---|
965 | * <p>Formatting shortcuts that will be translated into their longer version. |
---|
966 | * Be sure that format shortcuts do not refer to themselves: this will cause an infinite loop.</p> |
---|
967 | * |
---|
968 | * <p>Format codes and format shortcuts can be redefined after the jsDate |
---|
969 | * module is imported.</p> |
---|
970 | * |
---|
971 | * <p>Note that if you redefine the whole hash (object), you must supply a "matcher" |
---|
972 | * regex for the parser. The default matcher is:</p> |
---|
973 | * |
---|
974 | * <code>/()%(#?(%|[a-z]))/i</code> |
---|
975 | * |
---|
976 | * <p>which corresponds to the Perl syntax used by default.</p> |
---|
977 | * |
---|
978 | * <p>By customizing the matcher and format codes, nearly any strftime functionality is possible.</p> |
---|
979 | */ |
---|
980 | |
---|
981 | jsDate.formats.perl = { |
---|
982 | codes: { |
---|
983 | // |
---|
984 | // 2-part regex matcher for format codes |
---|
985 | // |
---|
986 | // first match must be the character before the code (to account for escaping) |
---|
987 | // second match must be the format code character(s) |
---|
988 | // |
---|
989 | matcher: /()%(#?(%|[a-z]))/i, |
---|
990 | // year |
---|
991 | Y: 'FullYear', |
---|
992 | y: 'ShortYear.2', |
---|
993 | // month |
---|
994 | m: 'MonthNumber.2', |
---|
995 | '#m': 'MonthNumber', |
---|
996 | B: 'MonthName', |
---|
997 | b: 'AbbrMonthName', |
---|
998 | // day |
---|
999 | d: 'Date.2', |
---|
1000 | '#d': 'Date', |
---|
1001 | e: 'Date', |
---|
1002 | A: 'DayName', |
---|
1003 | a: 'AbbrDayName', |
---|
1004 | w: 'Day', |
---|
1005 | // hours |
---|
1006 | H: 'Hours.2', |
---|
1007 | '#H': 'Hours', |
---|
1008 | I: 'Hours12.2', |
---|
1009 | '#I': 'Hours12', |
---|
1010 | p: 'AMPM', |
---|
1011 | // minutes |
---|
1012 | M: 'Minutes.2', |
---|
1013 | '#M': 'Minutes', |
---|
1014 | // seconds |
---|
1015 | S: 'Seconds.2', |
---|
1016 | '#S': 'Seconds', |
---|
1017 | s: 'Unix', |
---|
1018 | // milliseconds |
---|
1019 | N: 'Milliseconds.3', |
---|
1020 | '#N': 'Milliseconds', |
---|
1021 | // timezone |
---|
1022 | O: 'TimezoneOffset', |
---|
1023 | Z: 'TimezoneName', |
---|
1024 | G: 'GmtOffset' |
---|
1025 | }, |
---|
1026 | |
---|
1027 | shortcuts: { |
---|
1028 | // date |
---|
1029 | F: '%Y-%m-%d', |
---|
1030 | // time |
---|
1031 | T: '%H:%M:%S', |
---|
1032 | X: '%H:%M:%S', |
---|
1033 | // local format date |
---|
1034 | x: '%m/%d/%y', |
---|
1035 | D: '%m/%d/%y', |
---|
1036 | // local format extended |
---|
1037 | '#c': '%a %b %e %H:%M:%S %Y', |
---|
1038 | // local format short |
---|
1039 | v: '%e-%b-%Y', |
---|
1040 | R: '%H:%M', |
---|
1041 | r: '%I:%M:%S %p', |
---|
1042 | // tab and newline |
---|
1043 | t: '\t', |
---|
1044 | n: '\n', |
---|
1045 | '%': '%' |
---|
1046 | } |
---|
1047 | }; |
---|
1048 | |
---|
1049 | /** |
---|
1050 | * PHP format codes and shortcuts for strftime. |
---|
1051 | * |
---|
1052 | * A hash (object) of codes where each code must be an array where the first member is |
---|
1053 | * the name of a Date.prototype or jsDate.prototype function to call |
---|
1054 | * and optionally a second member indicating the number to pass to addZeros() |
---|
1055 | * |
---|
1056 | * <p>The following format codes are defined:</p> |
---|
1057 | * |
---|
1058 | * <pre class="code"> |
---|
1059 | * Code Result Description |
---|
1060 | * === Days === |
---|
1061 | * %a Sun through Sat An abbreviated textual representation of the day |
---|
1062 | * %A Sunday - Saturday A full textual representation of the day |
---|
1063 | * %d 01 to 31 Two-digit day of the month (with leading zeros) |
---|
1064 | * %e 1 to 31 Day of the month, with a space preceding single digits. |
---|
1065 | * %j 001 to 366 Day of the year, 3 digits with leading zeros |
---|
1066 | * %u 1 - 7 (Mon - Sun) ISO-8601 numeric representation of the day of the week |
---|
1067 | * %w 0 - 6 (Sun - Sat) Numeric representation of the day of the week |
---|
1068 | * |
---|
1069 | * === Week === |
---|
1070 | * %U 13 Full Week number, starting with the first Sunday as the first week |
---|
1071 | * %V 01 through 53 ISO-8601:1988 week number, starting with the first week of the year |
---|
1072 | * with at least 4 weekdays, with Monday being the start of the week |
---|
1073 | * %W 46 A numeric representation of the week of the year, |
---|
1074 | * starting with the first Monday as the first week |
---|
1075 | * === Month === |
---|
1076 | * %b Jan through Dec Abbreviated month name, based on the locale |
---|
1077 | * %B January - December Full month name, based on the locale |
---|
1078 | * %h Jan through Dec Abbreviated month name, based on the locale (an alias of %b) |
---|
1079 | * %m 01 - 12 (Jan - Dec) Two digit representation of the month |
---|
1080 | * |
---|
1081 | * === Year === |
---|
1082 | * %C 19 Two digit century (year/100, truncated to an integer) |
---|
1083 | * %y 09 for 2009 Two digit year |
---|
1084 | * %Y 2038 Four digit year |
---|
1085 | * |
---|
1086 | * === Time === |
---|
1087 | * %H 00 through 23 Two digit representation of the hour in 24-hour format |
---|
1088 | * %I 01 through 12 Two digit representation of the hour in 12-hour format |
---|
1089 | * %l 1 through 12 Hour in 12-hour format, with a space preceeding single digits |
---|
1090 | * %M 00 through 59 Two digit representation of the minute |
---|
1091 | * %p AM/PM UPPER-CASE 'AM' or 'PM' based on the given time |
---|
1092 | * %P am/pm lower-case 'am' or 'pm' based on the given time |
---|
1093 | * %r 09:34:17 PM Same as %I:%M:%S %p |
---|
1094 | * %R 00:35 Same as %H:%M |
---|
1095 | * %S 00 through 59 Two digit representation of the second |
---|
1096 | * %T 21:34:17 Same as %H:%M:%S |
---|
1097 | * %X 03:59:16 Preferred time representation based on locale, without the date |
---|
1098 | * %z -0500 or EST Either the time zone offset from UTC or the abbreviation |
---|
1099 | * %Z -0500 or EST The time zone offset/abbreviation option NOT given by %z |
---|
1100 | * |
---|
1101 | * === Time and Date === |
---|
1102 | * %D 02/05/09 Same as %m/%d/%y |
---|
1103 | * %F 2009-02-05 Same as %Y-%m-%d (commonly used in database datestamps) |
---|
1104 | * %s 305815200 Unix Epoch Time timestamp (same as the time() function) |
---|
1105 | * %x 02/05/09 Preferred date representation, without the time |
---|
1106 | * |
---|
1107 | * === Miscellaneous === |
---|
1108 | * %n --- A newline character (\n) |
---|
1109 | * %t --- A Tab character (\t) |
---|
1110 | * %% --- A literal percentage character (%) |
---|
1111 | * </pre> |
---|
1112 | */ |
---|
1113 | |
---|
1114 | jsDate.formats.php = { |
---|
1115 | codes: { |
---|
1116 | // |
---|
1117 | // 2-part regex matcher for format codes |
---|
1118 | // |
---|
1119 | // first match must be the character before the code (to account for escaping) |
---|
1120 | // second match must be the format code character(s) |
---|
1121 | // |
---|
1122 | matcher: /()%((%|[a-z]))/i, |
---|
1123 | // day |
---|
1124 | a: 'AbbrDayName', |
---|
1125 | A: 'DayName', |
---|
1126 | d: 'Date.2', |
---|
1127 | e: 'Date', |
---|
1128 | j: 'DayOfYear.3', |
---|
1129 | u: 'DayOfWeek', |
---|
1130 | w: 'Day', |
---|
1131 | // week |
---|
1132 | U: 'FullWeekOfYear.2', |
---|
1133 | V: 'IsoWeek.2', |
---|
1134 | W: 'WeekOfYear.2', |
---|
1135 | // month |
---|
1136 | b: 'AbbrMonthName', |
---|
1137 | B: 'MonthName', |
---|
1138 | m: 'MonthNumber.2', |
---|
1139 | h: 'AbbrMonthName', |
---|
1140 | // year |
---|
1141 | C: 'Century.2', |
---|
1142 | y: 'ShortYear.2', |
---|
1143 | Y: 'FullYear', |
---|
1144 | // time |
---|
1145 | H: 'Hours.2', |
---|
1146 | I: 'Hours12.2', |
---|
1147 | l: 'Hours12', |
---|
1148 | p: 'AMPM', |
---|
1149 | P: 'AmPm', |
---|
1150 | M: 'Minutes.2', |
---|
1151 | S: 'Seconds.2', |
---|
1152 | s: 'Unix', |
---|
1153 | O: 'TimezoneOffset', |
---|
1154 | z: 'GmtOffset', |
---|
1155 | Z: 'TimezoneAbbr' |
---|
1156 | }, |
---|
1157 | |
---|
1158 | shortcuts: { |
---|
1159 | D: '%m/%d/%y', |
---|
1160 | F: '%Y-%m-%d', |
---|
1161 | T: '%H:%M:%S', |
---|
1162 | X: '%H:%M:%S', |
---|
1163 | x: '%m/%d/%y', |
---|
1164 | R: '%H:%M', |
---|
1165 | r: '%I:%M:%S %p', |
---|
1166 | t: '\t', |
---|
1167 | n: '\n', |
---|
1168 | '%': '%' |
---|
1169 | } |
---|
1170 | }; |
---|
1171 | // |
---|
1172 | // Conceptually, the logic implemented here is similar to Ken Snyder's Date Instance Methods. |
---|
1173 | // I use his idea of a set of parsers which can be regular expressions or functions, |
---|
1174 | // iterating through those, and then seeing if Date.parse() will create a date. |
---|
1175 | // The parser expressions and functions are a little different and some bugs have been |
---|
1176 | // worked out. Also, a lot of "pre-parsing" is done to fix implementation |
---|
1177 | // variations of Date.parse() between browsers. |
---|
1178 | // |
---|
1179 | jsDate.createDate = function(date) { |
---|
1180 | // if passing in multiple arguments, try Date constructor |
---|
1181 | if (date == null) { |
---|
1182 | return new Date(); |
---|
1183 | } |
---|
1184 | // If the passed value is already a date object, return it |
---|
1185 | if (date instanceof Date) { |
---|
1186 | return date; |
---|
1187 | } |
---|
1188 | // if (typeof date == 'number') return new Date(date * 1000); |
---|
1189 | // If the passed value is an integer, interpret it as a javascript timestamp |
---|
1190 | if (typeof date == 'number') { |
---|
1191 | return new Date(date); |
---|
1192 | } |
---|
1193 | |
---|
1194 | // Before passing strings into Date.parse(), have to normalize them for certain conditions. |
---|
1195 | // If strings are not formatted staccording to the EcmaScript spec, results from Date parse will be implementation dependent. |
---|
1196 | // |
---|
1197 | // For example: |
---|
1198 | // * FF and Opera assume 2 digit dates are pre y2k, Chome assumes <50 is pre y2k, 50+ is 21st century. |
---|
1199 | // * Chrome will correctly parse '1984-1-25' into localtime, FF and Opera will not parse. |
---|
1200 | // * Both FF, Chrome and Opera will parse '1984/1/25' into localtime. |
---|
1201 | |
---|
1202 | // remove leading and trailing spaces |
---|
1203 | var parsable = String(date).replace(/^\s*(.+)\s*$/g, '$1'); |
---|
1204 | |
---|
1205 | // replace dahses (-) with slashes (/) in dates like n[nnn]/n[n]/n[nnn] |
---|
1206 | parsable = parsable.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/, "$1/$2/$3"); |
---|
1207 | |
---|
1208 | ///////// |
---|
1209 | // Need to check for '15-Dec-09' also. |
---|
1210 | // FF will not parse, but Chrome will. |
---|
1211 | // Chrome will set date to 2009 as well. |
---|
1212 | ///////// |
---|
1213 | |
---|
1214 | // first check for 'dd-mmm-yyyy' or 'dd/mmm/yyyy' like '15-Dec-2010' |
---|
1215 | parsable = parsable.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i, "$1 $2 $3"); |
---|
1216 | |
---|
1217 | // Now check for 'dd-mmm-yy' or 'dd/mmm/yy' and normalize years to default century. |
---|
1218 | var match = parsable.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i); |
---|
1219 | if (match && match.length > 3) { |
---|
1220 | var m3 = parseFloat(match[3]); |
---|
1221 | var ny = jsDate.config.defaultCentury + m3; |
---|
1222 | ny = String(ny); |
---|
1223 | |
---|
1224 | // now replace 2 digit year with 4 digit year |
---|
1225 | parsable = parsable.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i, match[1] +' '+ match[2] +' '+ ny); |
---|
1226 | |
---|
1227 | } |
---|
1228 | |
---|
1229 | // Check for '1/19/70 8:14PM' |
---|
1230 | // where starts with mm/dd/yy or yy/mm/dd and have something after |
---|
1231 | // Check if 1st postiion is greater than 31, assume it is year. |
---|
1232 | // Assme all 2 digit years are 1900's. |
---|
1233 | // Finally, change them into US style mm/dd/yyyy representations. |
---|
1234 | match = parsable.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/); |
---|
1235 | |
---|
1236 | function h1(parsable, match) { |
---|
1237 | var m1 = parseFloat(match[1]); |
---|
1238 | var m2 = parseFloat(match[2]); |
---|
1239 | var m3 = parseFloat(match[3]); |
---|
1240 | var cent = jsDate.config.defaultCentury; |
---|
1241 | var ny, nd, nm, str; |
---|
1242 | |
---|
1243 | if (m1 > 31) { // first number is a year |
---|
1244 | nd = m3; |
---|
1245 | nm = m2; |
---|
1246 | ny = cent + m1; |
---|
1247 | } |
---|
1248 | |
---|
1249 | else { // last number is the year |
---|
1250 | nd = m2; |
---|
1251 | nm = m1; |
---|
1252 | ny = cent + m3; |
---|
1253 | } |
---|
1254 | |
---|
1255 | str = nm+'/'+nd+'/'+ny; |
---|
1256 | |
---|
1257 | // now replace 2 digit year with 4 digit year |
---|
1258 | return parsable.replace(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/, str); |
---|
1259 | |
---|
1260 | } |
---|
1261 | |
---|
1262 | if (match && match.length > 3) { |
---|
1263 | parsable = h1(parsable, match); |
---|
1264 | } |
---|
1265 | |
---|
1266 | // Now check for '1/19/70' with nothing after and do as above |
---|
1267 | var match = parsable.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/); |
---|
1268 | |
---|
1269 | if (match && match.length > 3) { |
---|
1270 | parsable = h1(parsable, match); |
---|
1271 | } |
---|
1272 | |
---|
1273 | |
---|
1274 | var i = 0; |
---|
1275 | var length = jsDate.matchers.length; |
---|
1276 | var pattern, |
---|
1277 | ms, |
---|
1278 | current = parsable; |
---|
1279 | while (i < length) { |
---|
1280 | ms = Date.parse(current); |
---|
1281 | if (!isNaN(ms)) { |
---|
1282 | return new Date(ms); |
---|
1283 | } |
---|
1284 | pattern = jsDate.matchers[i]; |
---|
1285 | if (typeof pattern == 'function') { |
---|
1286 | var obj = pattern.call(jsDate, current); |
---|
1287 | if (obj instanceof Date) { |
---|
1288 | return obj; |
---|
1289 | } |
---|
1290 | } else { |
---|
1291 | current = parsable.replace(pattern[0], pattern[1]); |
---|
1292 | } |
---|
1293 | i++; |
---|
1294 | } |
---|
1295 | return NaN; |
---|
1296 | }; |
---|
1297 | |
---|
1298 | |
---|
1299 | /** |
---|
1300 | * @static |
---|
1301 | * Handy static utility function to return the number of days in a given month. |
---|
1302 | * @param {Integer} year Year |
---|
1303 | * @param {Integer} month Month (1-12) |
---|
1304 | * @returns {Integer} Number of days in the month. |
---|
1305 | */ |
---|
1306 | // |
---|
1307 | // handy utility method Borrowed right from Ken Snyder's Date Instance Mehtods. |
---|
1308 | // |
---|
1309 | jsDate.daysInMonth = function(year, month) { |
---|
1310 | if (month == 2) { |
---|
1311 | return new Date(year, 1, 29).getDate() == 29 ? 29 : 28; |
---|
1312 | } |
---|
1313 | return [undefined,31,undefined,31,30,31,30,31,31,30,31,30,31][month]; |
---|
1314 | }; |
---|
1315 | |
---|
1316 | |
---|
1317 | // |
---|
1318 | // An Array of regular expressions or functions that will attempt to match the date string. |
---|
1319 | // Functions are called with scope of a jsDate instance. |
---|
1320 | // |
---|
1321 | jsDate.matchers = [ |
---|
1322 | // convert dd.mmm.yyyy to mm/dd/yyyy (world date to US date). |
---|
1323 | [/(3[01]|[0-2]\d)\s*\.\s*(1[0-2]|0\d)\s*\.\s*([1-9]\d{3})/, '$2/$1/$3'], |
---|
1324 | // convert yyyy-mm-dd to mm/dd/yyyy (ISO date to US date). |
---|
1325 | [/([1-9]\d{3})\s*-\s*(1[0-2]|0\d)\s*-\s*(3[01]|[0-2]\d)/, '$2/$3/$1'], |
---|
1326 | // Handle 12 hour or 24 hour time with milliseconds am/pm and optional date part. |
---|
1327 | function(str) { |
---|
1328 | var match = str.match(/^(?:(.+)\s+)?([012]?\d)(?:\s*\:\s*(\d\d))?(?:\s*\:\s*(\d\d(\.\d*)?))?\s*(am|pm)?\s*$/i); |
---|
1329 | // opt. date hour opt. minute opt. second opt. msec opt. am or pm |
---|
1330 | if (match) { |
---|
1331 | if (match[1]) { |
---|
1332 | var d = this.createDate(match[1]); |
---|
1333 | if (isNaN(d)) { |
---|
1334 | return; |
---|
1335 | } |
---|
1336 | } else { |
---|
1337 | var d = new Date(); |
---|
1338 | d.setMilliseconds(0); |
---|
1339 | } |
---|
1340 | var hour = parseFloat(match[2]); |
---|
1341 | if (match[6]) { |
---|
1342 | hour = match[6].toLowerCase() == 'am' ? (hour == 12 ? 0 : hour) : (hour == 12 ? 12 : hour + 12); |
---|
1343 | } |
---|
1344 | d.setHours(hour, parseInt(match[3] || 0, 10), parseInt(match[4] || 0, 10), ((parseFloat(match[5] || 0)) || 0)*1000); |
---|
1345 | return d; |
---|
1346 | } |
---|
1347 | else { |
---|
1348 | return str; |
---|
1349 | } |
---|
1350 | }, |
---|
1351 | // Handle ISO timestamp with time zone. |
---|
1352 | function(str) { |
---|
1353 | var match = str.match(/^(?:(.+))[T|\s+]([012]\d)(?:\:(\d\d))(?:\:(\d\d))(?:\.\d+)([\+\-]\d\d\:\d\d)$/i); |
---|
1354 | if (match) { |
---|
1355 | if (match[1]) { |
---|
1356 | var d = this.createDate(match[1]); |
---|
1357 | if (isNaN(d)) { |
---|
1358 | return; |
---|
1359 | } |
---|
1360 | } else { |
---|
1361 | var d = new Date(); |
---|
1362 | d.setMilliseconds(0); |
---|
1363 | } |
---|
1364 | var hour = parseFloat(match[2]); |
---|
1365 | d.setHours(hour, parseInt(match[3], 10), parseInt(match[4], 10), parseFloat(match[5])*1000); |
---|
1366 | return d; |
---|
1367 | } |
---|
1368 | else { |
---|
1369 | return str; |
---|
1370 | } |
---|
1371 | }, |
---|
1372 | // Try to match ambiguous strings like 12/8/22. |
---|
1373 | // Use FF date assumption that 2 digit years are 20th century (i.e. 1900's). |
---|
1374 | // This may be redundant with pre processing of date already performed. |
---|
1375 | function(str) { |
---|
1376 | var match = str.match(/^([0-3]?\d)\s*[-\/.\s]{1}\s*([a-zA-Z]{3,9})\s*[-\/.\s]{1}\s*([0-3]?\d)$/); |
---|
1377 | if (match) { |
---|
1378 | var d = new Date(); |
---|
1379 | var cent = jsDate.config.defaultCentury; |
---|
1380 | var m1 = parseFloat(match[1]); |
---|
1381 | var m3 = parseFloat(match[3]); |
---|
1382 | var ny, nd, nm; |
---|
1383 | if (m1 > 31) { // first number is a year |
---|
1384 | nd = m3; |
---|
1385 | ny = cent + m1; |
---|
1386 | } |
---|
1387 | |
---|
1388 | else { // last number is the year |
---|
1389 | nd = m1; |
---|
1390 | ny = cent + m3; |
---|
1391 | } |
---|
1392 | |
---|
1393 | var nm = inArray(match[2], jsDate.regional[this.locale]["monthNamesShort"]); |
---|
1394 | |
---|
1395 | if (nm == -1) { |
---|
1396 | nm = inArray(match[2], jsDate.regional[this.locale]["monthNames"]); |
---|
1397 | } |
---|
1398 | |
---|
1399 | d.setFullYear(ny, nm, nd); |
---|
1400 | d.setHours(0,0,0,0); |
---|
1401 | return d; |
---|
1402 | } |
---|
1403 | |
---|
1404 | else { |
---|
1405 | return str; |
---|
1406 | } |
---|
1407 | } |
---|
1408 | ]; |
---|
1409 | |
---|
1410 | // |
---|
1411 | // I think John Reisig published this method on his blog, ejohn. |
---|
1412 | // |
---|
1413 | function inArray( elem, array ) { |
---|
1414 | if ( array.indexOf ) { |
---|
1415 | return array.indexOf( elem ); |
---|
1416 | } |
---|
1417 | |
---|
1418 | for ( var i = 0, length = array.length; i < length; i++ ) { |
---|
1419 | if ( array[ i ] === elem ) { |
---|
1420 | return i; |
---|
1421 | } |
---|
1422 | } |
---|
1423 | |
---|
1424 | return -1; |
---|
1425 | } |
---|
1426 | |
---|
1427 | // |
---|
1428 | // Thanks to Kangax, Christian Sciberras and Stack Overflow for this method. |
---|
1429 | // |
---|
1430 | function get_type(thing){ |
---|
1431 | if(thing===null) return "[object Null]"; // special case |
---|
1432 | return Object.prototype.toString.call(thing); |
---|
1433 | } |
---|
1434 | |
---|
1435 | $.jsDate = jsDate; |
---|
1436 | |
---|
1437 | })(jQuery); |
---|