1 /** 2 * @class The built-in Date class. 3 * @name Date 4 */ 5 6 Date.__parse__ = Date.parse; 7 8 /** 9 * Parses a date from a string, optionally using the specified formatting. If 10 * only a single argument is specified (i.e., <tt>format</tt> is not specified), 11 * this method invokes the native implementation to guarantee 12 * backwards-compatibility. 13 * 14 * <p>The format string is in the same format expected by the <tt>strptime</tt> 15 * function in C. The following conversion specifications are supported:<ul> 16 * 17 * <li>%b - abbreviated month names.</li> 18 * <li>%B - full month names.</li> 19 * <li>%h - same as %b.</li> 20 * <li>%d - day of month [1,31].</li> 21 * <li>%e - same as %d.</li> 22 * <li>%H - hour (24-hour clock) [0,23].</li> 23 * <li>%m - month number [1,12].</li> 24 * <li>%M - minute [0,59].</li> 25 * <li>%S - second [0,61].</li> 26 * <li>%y - year with century [0,99].</li> 27 * <li>%Y - year including century.</li> 28 * <li>%% - %.</li> 29 * 30 * </ul>The following conversion specifications are <i>unsupported</i> (for now):<ul> 31 * 32 * <li>%a - day of week, either abbreviated or full name.</li> 33 * <li>%A - same as %a.</li> 34 * <li>%c - locale's appropriate date and time.</li> 35 * <li>%C - century number.</li> 36 * <li>%D - same as %m/%d/%y.</li> 37 * <li>%I - hour (12-hour clock) [1,12].</li> 38 * <li>%j - day number [1,366].</li> 39 * <li>%n - any white space.</li> 40 * <li>%p - locale's equivalent of a.m. or p.m.</li> 41 * <li>%r - same as %I:%M:%S %p.</li> 42 * <li>%R - same as %H:%M.</li> 43 * <li>%t - same as %n.</li> 44 * <li>%T - same as %H:%M:%S.</li> 45 * <li>%U - week number [0,53].</li> 46 * <li>%w - weekday [0,6].</li> 47 * <li>%W - week number [0,53].</li> 48 * <li>%x - locale's equivalent to %m/%d/%y.</li> 49 * <li>%X - locale's equivalent to %I:%M:%S %p.</li> 50 * 51 * </ul> 52 * 53 * @see <a 54 * href="http://www.opengroup.org/onlinepubs/007908799/xsh/strptime.html">strptime</a> 55 * documentation. 56 * @param {string} s the string to parse as a date. 57 * @param {string} [format] an optional format string. 58 * @returns {Date} the parsed date. 59 */ 60 Date.parse = function(s, format) { 61 if (arguments.length == 1) { 62 return Date.__parse__(s); 63 } 64 65 var year = 1970, month = 0, date = 1, hour = 0, minute = 0, second = 0; 66 var fields = [function() {}]; 67 format = format.replace(/[\\\^\$\*\+\?\[\]\(\)\.\{\}]/g, "\\$&"); 68 format = format.replace(/%[a-zA-Z0-9]/g, function(s) { 69 switch (s) { 70 // TODO %a: day of week, either abbreviated or full name 71 // TODO %A: same as %a 72 case '%b': { 73 fields.push(function(x) { month = { 74 Jan: 0, Feb: 1, Mar: 2, Apr: 3, May: 4, Jun: 5, Jul: 6, Aug: 7, 75 Sep: 8, Oct: 9, Nov: 10, Dec: 11 76 }[x]; }); 77 return "([A-Za-z]+)"; 78 } 79 case '%h': 80 case '%B': { 81 fields.push(function(x) { month = { 82 January: 0, February: 1, March: 2, April: 3, May: 4, June: 5, 83 July: 6, August: 7, September: 8, October: 9, November: 10, 84 December: 11 85 }[x]; }); 86 return "([A-Za-z]+)"; 87 } 88 // TODO %c: locale's appropriate date and time 89 // TODO %C: century number[0,99] 90 case '%e': 91 case '%d': { 92 fields.push(function(x) { date = x; }); 93 return "([0-9]+)"; 94 } 95 // TODO %D: same as %m/%d/%y 96 case '%H': { 97 fields.push(function(x) { hour = x; }); 98 return "([0-9]+)"; 99 } 100 // TODO %I: hour (12-hour clock) [1,12] 101 // TODO %j: day number [1,366] 102 case '%m': { 103 fields.push(function(x) { month = x - 1; }); 104 return "([0-9]+)"; 105 } 106 case '%M': { 107 fields.push(function(x) { minute = x; }); 108 return "([0-9]+)"; 109 } 110 // TODO %n: any white space 111 // TODO %p: locale's equivalent of a.m. or p.m. 112 // TODO %r: %I:%M:%S %p 113 // TODO %R: %H:%M 114 case '%S': { 115 fields.push(function(x) { second = x; }); 116 return "([0-9]+)"; 117 } 118 // TODO %t: any white space 119 // TODO %T: %H:%M:%S 120 // TODO %U: week number [00,53] 121 // TODO %w: weekday [0,6] 122 // TODO %W: week number [00, 53] 123 // TODO %x: locale date (%m/%d/%y) 124 // TODO %X: locale time (%I:%M:%S %p) 125 case '%y': { 126 fields.push(function(x) { 127 x = Number(x); 128 year = x + (((0 <= x) && (x < 69)) ? 2000 129 : (((x >= 69) && (x < 100) ? 1900 : 0))); 130 }); 131 return "([0-9]+)"; 132 } 133 case '%Y': { 134 fields.push(function(x) { year = x; }); 135 return "([0-9]+)"; 136 } 137 case '%%': { 138 fields.push(function() {}); 139 return "%"; 140 } 141 } 142 return s; 143 }); 144 145 var match = s.match(format); 146 if (match) match.forEach(function(m, i) { fields[i](m); }); 147 return new Date(year, month, date, hour, minute, second); 148 }; 149 150 if (Date.prototype.toLocaleFormat) { 151 Date.prototype.format = Date.prototype.toLocaleFormat; 152 } else { 153 154 /** 155 * Converts a date to a string using the specified formatting. If the 156 * <tt>Date</tt> object already supports the <tt>toLocaleFormat</tt> method, as 157 * in Firefox, this is simply an alias to the built-in method. 158 * 159 * <p>The format string is in the same format expected by the <tt>strftime</tt> 160 * function in C. The following conversion specifications are supported:<ul> 161 * 162 * <li>%a - abbreviated weekday name.</li> 163 * <li>%A - full weekday name.</li> 164 * <li>%b - abbreviated month names.</li> 165 * <li>%B - full month names.</li> 166 * <li>%c - locale's appropriate date and time.</li> 167 * <li>%C - century number.</li> 168 * <li>%d - day of month [01,31] (zero padded).</li> 169 * <li>%D - same as %m/%d/%y.</li> 170 * <li>%e - day of month [ 1,31] (space padded).</li> 171 * <li>%h - same as %b.</li> 172 * <li>%H - hour (24-hour clock) [00,23] (zero padded).</li> 173 * <li>%I - hour (12-hour clock) [01,12] (zero padded).</li> 174 * <li>%m - month number [01,12] (zero padded).</li> 175 * <li>%M - minute [0,59] (zero padded).</li> 176 * <li>%n - newline character.</li> 177 * <li>%p - locale's equivalent of a.m. or p.m.</li> 178 * <li>%r - same as %I:%M:%S %p.</li> 179 * <li>%R - same as %H:%M.</li> 180 * <li>%S - second [00,61] (zero padded).</li> 181 * <li>%t - tab character.</li> 182 * <li>%T - same as %H:%M:%S.</li> 183 * <li>%x - same as %m/%d/%y.</li> 184 * <li>%X - same as %I:%M:%S %p.</li> 185 * <li>%y - year with century [00,99] (zero padded).</li> 186 * <li>%Y - year including century.</li> 187 * <li>%% - %.</li> 188 * 189 * </ul>The following conversion specifications are <i>unsupported</i> (for now):<ul> 190 * 191 * <li>%j - day number [1,366].</li> 192 * <li>%u - weekday number [1,7].</li> 193 * <li>%U - week number [00,53].</li> 194 * <li>%V - week number [01,53].</li> 195 * <li>%w - weekday number [0,6].</li> 196 * <li>%W - week number [00,53].</li> 197 * <li>%Z - timezone name or abbreviation.</li> 198 * 199 * </ul> 200 * 201 * @see <a 202 * href="http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/toLocaleFormat">Date.toLocaleFormat</a> 203 * documentation. 204 * @see <a 205 * href="http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html">strftime</a> 206 * documentation. 207 * @param {string} format a format string. 208 * @returns {string} the formatted date. 209 */ 210 Date.prototype.format = function(format) { 211 function pad(n, p) { return (n < 10) ? (p || "0") + n : n; } 212 var d = this; 213 return format.replace(/%[a-zA-Z0-9]/g, function(s) { 214 switch (s) { 215 case '%a': return [ 216 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 217 ][d.getDay()]; 218 case '%A': return [ 219 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 220 "Saturday", 221 ][d.getDay()]; 222 case '%h': 223 case '%b': return [ 224 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", 225 "Oct", "Nov", "Dec", 226 ][d.getMonth()]; 227 case '%B': return [ 228 "January", "February", "March", "April", "May", "June", "July", 229 "August", "September", "October", "November", "December", 230 ][d.getMonth()]; 231 case '%c': return d.toLocaleString(); 232 case '%C': return pad(Math.floor(d.getFullYear() / 100) % 100); 233 case '%d': return pad(d.getDate()); 234 case '%x': 235 case '%D': return pad(d.getMonth() + 1) 236 + "/" + pad(d.getDate()) 237 + "/" + pad(d.getFullYear() % 100); 238 case '%e': return pad(d.getDate(), " "); 239 case '%H': return pad(d.getHours()); 240 case '%I': { 241 var h = d.getHours() % 12; 242 return h ? pad(h) : 12; 243 } 244 // TODO %j: day of year as a decimal number [001,366] 245 case '%m': return pad(d.getMonth() + 1); 246 case '%M': return pad(d.getMinutes()); 247 case '%n': return "\n"; 248 case '%p': return d.getHours() < 12 ? "AM" : "PM"; 249 case '%T': 250 case '%X': 251 case '%r': { 252 var h = d.getHours() % 12; 253 return (h ? pad(h) : 12) 254 + ":" + pad(d.getMinutes()) 255 + ":" + pad(d.getSeconds()) 256 + " " + (d.getHours() < 12 ? "AM" : "PM"); 257 } 258 case '%R': return pad(d.getHours()) + ":" + pad(d.getMinutes()); 259 case '%S': return pad(d.getSeconds()); 260 case '%t': return "\t"; 261 case '%u': { 262 var w = d.getDay(); 263 return w ? w : 1; 264 } 265 // TODO %U: week number (sunday first day) [00,53] 266 // TODO %V: week number (monday first day) [01,53] ... with weirdness 267 case '%w': return d.getDay(); 268 // TODO %W: week number (monday first day) [00,53] ... with weirdness 269 case '%y': return pad(d.getFullYear() % 100); 270 case '%Y': return d.getFullYear(); 271 // TODO %Z: timezone name or abbreviation 272 case '%%': return "%"; 273 } 274 return s; 275 }); 276 }; 277 } 278