1 // ===================================================================
2 // Author: Matt Kruse <matt@mattkruse.com>
3 // WWW: http://www.mattkruse.com/
5 // NOTICE: You may use this code for any purpose, commercial or
6 // private, without any further permission from the author. You may
7 // remove this notice from your final code if you wish, however it is
8 // appreciated by the author if at least my web site address is kept.
10 // You may *NOT* re-distribute this code in any way except through its
11 // use. That means, you can include it in your product, or your web
12 // site, or any other form where the code is actually being used. You
13 // may not put the plain javascript up on your site for download or
14 // include it in your javascript libraries for download.
15 // If you wish to share this code with others, please just point them
16 // to the URL instead.
17 // Please DO NOT link directly to my .js files from your site. Copy
18 // the files to your server and use them there. Thank you.
19 // ===================================================================
22 // ------------------------------------------------------------------
23 // May 17, 2003: Fixed bug in parseDate() for dates <1970
24 // March 11, 2003: Added parseDate() function
25 // March 11, 2003: Added "NNN" formatting option. Doesn't match up
26 // perfectly with SimpleDateFormat formats, but
27 // backwards-compatability was required.
29 // ------------------------------------------------------------------
30 // These functions use the same 'format' strings as the
31 // java.text.SimpleDateFormat class, with minor exceptions.
32 // The format string consists of the following abbreviations:
34 // Field | Full Form | Short Form
35 // -------------+--------------------+-----------------------
36 // Year | yyyy (4 digits) | yy (2 digits), y (2 or 4 digits)
37 // Month | MMM (name or abbr.)| MM (2 digits), M (1 or 2 digits)
39 // Day of Month | dd (2 digits) | d (1 or 2 digits)
40 // Day of Week | EE (name) | E (abbr)
41 // Hour (1-12) | hh (2 digits) | h (1 or 2 digits)
42 // Hour (0-23) | HH (2 digits) | H (1 or 2 digits)
43 // Hour (0-11) | KK (2 digits) | K (1 or 2 digits)
44 // Hour (1-24) | kk (2 digits) | k (1 or 2 digits)
45 // Minute | mm (2 digits) | m (1 or 2 digits)
46 // Second | ss (2 digits) | s (1 or 2 digits)
49 // NOTE THE DIFFERENCE BETWEEN MM and mm! Month=MM, not mm!
51 // "MMM d, y" matches: January 01, 2000
54 // "M/d/yy" matches: 01/20/00
56 // "MMM dd, yyyy hh:mm:ssa" matches: "January 01, 2000 12:30:45AM"
57 // ------------------------------------------------------------------
59 var MONTH_NAMES
=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
60 var DAY_NAMES
=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
61 function LZ(x
) {return(x
<0||x
>9?"":"0")+x
}
63 // ------------------------------------------------------------------
64 // isDate ( date_string, format_string )
65 // Returns true if date string matches format of format string and
66 // is a valid date. Else returns false.
67 // It is recommended that you trim whitespace around the value before
68 // passing it to this function, as whitespace is NOT ignored!
69 // ------------------------------------------------------------------
70 function isDate(val
,format
) {
71 var date
=getDateFromFormat(val
,format
);
72 if (date
==0) { return false; }
76 // -------------------------------------------------------------------
77 // compareDates(date1,date1format,date2,date2format)
78 // Compare two date strings to see which is greater.
80 // 1 if date1 is greater than date2
81 // 0 if date2 is greater than date1 of if they are the same
82 // -1 if either of the dates is in an invalid format
83 // -------------------------------------------------------------------
84 function compareDates(date1
,dateformat1
,date2
,dateformat2
) {
85 var d1
=getDateFromFormat(date1
,dateformat1
);
86 var d2
=getDateFromFormat(date2
,dateformat2
);
96 // ------------------------------------------------------------------
97 // formatDate (date_object, format)
98 // Returns a date in the output format specified.
99 // The format string uses the same abbreviations as in getDateFromFormat()
100 // ------------------------------------------------------------------
101 function formatDate(date
,format
) {
107 var y
=date
.getYear()+"";
108 var M
=date
.getMonth()+1;
109 var d
=date
.getDate();
111 var H
=date
.getHours();
112 var m
=date
.getMinutes();
113 var s
=date
.getSeconds();
114 var yyyy
,yy
,MMM
,MM
,dd
,hh
,h
,mm
,ss
,ampm
,HH
,H
,KK
,K
,kk
,k
;
115 // Convert real date parts into formatted versions
116 var value
=new Object();
117 if (y
.length
< 4) {y
=""+(y
-0+1900);}
120 value
["yy"]=y
.substring(2,4);
123 value
["MMM"]=MONTH_NAMES
[M
-1];
124 value
["NNN"]=MONTH_NAMES
[M
+11];
127 value
["E"]=DAY_NAMES
[E
+7];
128 value
["EE"]=DAY_NAMES
[E
];
131 if (H
==0){value
["h"]=12;}
132 else if (H
>12){value
["h"]=H
-12;}
134 value
["hh"]=LZ(value
["h"]);
135 if (H
>11){value
["K"]=H
-12;} else {value
["K"]=H
;}
137 value
["KK"]=LZ(value
["K"]);
138 value
["kk"]=LZ(value
["k"]);
139 if (H
> 11) { value
["a"]="PM"; }
140 else { value
["a"]="AM"; }
145 while (i_format
< format
.length
) {
146 c
=format
.charAt(i_format
);
148 while ((format
.charAt(i_format
)==c
) && (i_format
< format
.length
)) {
149 token
+= format
.charAt(i_format
++);
151 if (value
[token
] != null) { result
=result
+ value
[token
]; }
152 else { result
=result
+ token
; }
157 // ------------------------------------------------------------------
158 // Utility functions for parsing in getDateFromFormat()
159 // ------------------------------------------------------------------
160 function _isInteger(val
) {
161 var digits
="1234567890";
162 for (var i
=0; i
< val
.length
; i
++) {
163 if (digits
.indexOf(val
.charAt(i
))==-1) { return false; }
167 function _getInt(str
,i
,minlength
,maxlength
) {
168 for (var x
=maxlength
; x
>=minlength
; x
--) {
169 var token
=str
.substring(i
,i
+x
);
170 if (token
.length
< minlength
) { return null; }
171 if (_isInteger(token
)) { return token
; }
176 // ------------------------------------------------------------------
177 // getDateFromFormat( date_string , format_string )
179 // This function takes a date string and a format string. It matches
180 // If the date string matches the format string, it returns the
181 // getTime() of the date. If it does not match, it returns 0.
182 // ------------------------------------------------------------------
183 function getDateFromFormat(val
,format
) {
193 var year
=now
.getYear();
194 var month
=now
.getMonth()+1;
196 var hh
=now
.getHours();
197 var mm
=now
.getMinutes();
198 var ss
=now
.getSeconds();
201 while (i_format
< format
.length
) {
202 // Get next token from format string
203 c
=format
.charAt(i_format
);
205 while ((format
.charAt(i_format
)==c
) && (i_format
< format
.length
)) {
206 token
+= format
.charAt(i_format
++);
208 // Extract contents of value based on format token
209 if (token
=="yyyy" || token
=="yy" || token
=="y") {
210 if (token
=="yyyy") { x
=4;y
=4; }
211 if (token
=="yy") { x
=2;y
=2; }
212 if (token
=="y") { x
=2;y
=4; }
213 year
=_getInt(val
,i_val
,x
,y
);
214 if (year
==null) { return 0; }
215 i_val
+= year
.length
;
216 if (year
.length
==2) {
217 if (year
> 70) { year
=1900+(year
-0); }
218 else { year
=2000+(year
-0); }
221 else if (token
=="MMM"||token
=="NNN"){
223 for (var i
=0; i
<MONTH_NAMES
.length
; i
++) {
224 var month_name
=MONTH_NAMES
[i
];
225 if (val
.substring(i_val
,i_val
+month_name
.length
).toLowerCase()==month_name
.toLowerCase()) {
226 if (token
=="MMM"||(token
=="NNN"&&i
>11)) {
228 if (month
>12) { month
-= 12; }
229 i_val
+= month_name
.length
;
234 if ((month
< 1)||(month
>12)){return 0;}
236 else if (token
=="EE"||token
=="E"){
237 for (var i
=0; i
<DAY_NAMES
.length
; i
++) {
238 var day_name
=DAY_NAMES
[i
];
239 if (val
.substring(i_val
,i_val
+day_name
.length
).toLowerCase()==day_name
.toLowerCase()) {
240 i_val
+= day_name
.length
;
245 else if (token
=="MM"||token
=="M") {
246 month
=_getInt(val
,i_val
,token
.length
,2);
247 if(month
==null||(month
<1)||(month
>12)){return 0;}
248 i_val
+=month
.length
;}
249 else if (token
=="dd"||token
=="d") {
250 date
=_getInt(val
,i_val
,token
.length
,2);
251 if(date
==null||(date
<1)||(date
>31)){return 0;}
253 else if (token
=="hh"||token
=="h") {
254 hh
=_getInt(val
,i_val
,token
.length
,2);
255 if(hh
==null||(hh
<1)||(hh
>12)){return 0;}
257 else if (token
=="HH"||token
=="H") {
258 hh
=_getInt(val
,i_val
,token
.length
,2);
259 if(hh
==null||(hh
<0)||(hh
>23)){return 0;}
261 else if (token
=="KK"||token
=="K") {
262 hh
=_getInt(val
,i_val
,token
.length
,2);
263 if(hh
==null||(hh
<0)||(hh
>11)){return 0;}
265 else if (token
=="kk"||token
=="k") {
266 hh
=_getInt(val
,i_val
,token
.length
,2);
267 if(hh
==null||(hh
<1)||(hh
>24)){return 0;}
268 i_val
+=hh
.length
;hh
--;}
269 else if (token
=="mm"||token
=="m") {
270 mm
=_getInt(val
,i_val
,token
.length
,2);
271 if(mm
==null||(mm
<0)||(mm
>59)){return 0;}
273 else if (token
=="ss"||token
=="s") {
274 ss
=_getInt(val
,i_val
,token
.length
,2);
275 if(ss
==null||(ss
<0)||(ss
>59)){return 0;}
277 else if (token
=="a") {
278 if (val
.substring(i_val
,i_val
+2).toLowerCase()=="am") {ampm
="AM";}
279 else if (val
.substring(i_val
,i_val
+2).toLowerCase()=="pm") {ampm
="PM";}
283 if (val
.substring(i_val
,i_val
+token
.length
)!=token
) {return 0;}
284 else {i_val
+=token
.length
;}
287 // If there are any trailing characters left in the value, it doesn't match
288 if (i_val
!= val
.length
) { return 0; }
289 // Is date valid for month?
291 // Check for leap year
292 if ( ( (year
%4==0)&&(year
%100 != 0) ) || (year
%400==0) ) { // leap year
293 if (date
> 29){ return 0; }
295 else { if (date
> 28) { return 0; } }
297 if ((month
==4)||(month
==6)||(month
==9)||(month
==11)) {
298 if (date
> 30) { return 0; }
300 // Correct hours value
301 if (hh
<12 && ampm
=="PM") { hh
=hh
-0+12; }
302 else if (hh
>11 && ampm
=="AM") { hh
-=12; }
303 var newdate
=new Date(year
,month
-1,date
,hh
,mm
,ss
);
304 return newdate
.getTime();
307 // ------------------------------------------------------------------
308 // parseDate( date_string [, prefer_euro_format] )
310 // This function takes a date string and tries to match it to a
311 // number of possible date formats to get the value. It will try to
312 // match against the following international formats, in this order:
313 // y-M-d MMM d, y MMM d,y y-MMM-d d-MMM-y MMM d
314 // M/d/y M-d-y M.d.y MMM-d M/d M-d
315 // d/M/y d-M-y d.M.y d-MMM d/M d-M
316 // A second argument may be passed to instruct the method to search
317 // for formats like d/M/y (european format) before M/d/y (American).
318 // Returns a Date object or null if no patterns match.
319 // ------------------------------------------------------------------
320 function parseDate(val
) {
321 var preferEuro
=(arguments
.length
==2)?arguments
[1]:false;
322 generalFormats
=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d');
323 monthFirst
=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d');
324 dateFirst
=new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M');
325 var checkList
=new Array('generalFormats',preferEuro
?'dateFirst':'monthFirst',preferEuro
?'monthFirst':'dateFirst');
327 for (var i
=0; i
<checkList
.length
; i
++) {
328 var l
=window
[checkList
[i
]];
329 for (var j
=0; j
<l
.length
; j
++) {
330 d
=getDateFromFormat(val
,l
[j
]);
331 if (d
!=0) { return new Date(d
); }