/django/contrib/admin/media/js/dateparse.js
JavaScript | 239 lines | 201 code | 7 blank | 31 comment | 22 complexity | 81bc0017faa9db4b58c5c40d9ab87f62 MD5 | raw file
1/* 'Magic' date parsing, by Simon Willison (6th October 2003) 2 http://simon.incutio.com/archive/2003/10/06/betterDateInput 3 Adapted for 6newslawrence.com, 28th January 2004 4*/ 5 6/* Finds the index of the first occurence of item in the array, or -1 if not found */ 7if (typeof Array.prototype.indexOf == 'undefined') { 8 Array.prototype.indexOf = function(item) { 9 var len = this.length; 10 for (var i = 0; i < len; i++) { 11 if (this[i] == item) { 12 return i; 13 } 14 } 15 return -1; 16 }; 17} 18/* Returns an array of items judged 'true' by the passed in test function */ 19if (typeof Array.prototype.filter == 'undefined') { 20 Array.prototype.filter = function(test) { 21 var matches = []; 22 var len = this.length; 23 for (var i = 0; i < len; i++) { 24 if (test(this[i])) { 25 matches[matches.length] = this[i]; 26 } 27 } 28 return matches; 29 }; 30} 31 32var monthNames = gettext("January February March April May June July August September October November December").split(" "); 33var weekdayNames = gettext("Sunday Monday Tuesday Wednesday Thursday Friday Saturday").split(" "); 34 35/* Takes a string, returns the index of the month matching that string, throws 36 an error if 0 or more than 1 matches 37*/ 38function parseMonth(month) { 39 var matches = monthNames.filter(function(item) { 40 return new RegExp("^" + month, "i").test(item); 41 }); 42 if (matches.length == 0) { 43 throw new Error("Invalid month string"); 44 } 45 if (matches.length > 1) { 46 throw new Error("Ambiguous month"); 47 } 48 return monthNames.indexOf(matches[0]); 49} 50/* Same as parseMonth but for days of the week */ 51function parseWeekday(weekday) { 52 var matches = weekdayNames.filter(function(item) { 53 return new RegExp("^" + weekday, "i").test(item); 54 }); 55 if (matches.length == 0) { 56 throw new Error("Invalid day string"); 57 } 58 if (matches.length > 1) { 59 throw new Error("Ambiguous weekday"); 60 } 61 return weekdayNames.indexOf(matches[0]); 62} 63 64/* Array of objects, each has 're', a regular expression and 'handler', a 65 function for creating a date from something that matches the regular 66 expression. Handlers may throw errors if string is unparseable. 67*/ 68var dateParsePatterns = [ 69 // Today 70 { re: /^tod/i, 71 handler: function() { 72 return new Date(); 73 } 74 }, 75 // Tomorrow 76 { re: /^tom/i, 77 handler: function() { 78 var d = new Date(); 79 d.setDate(d.getDate() + 1); 80 return d; 81 } 82 }, 83 // Yesterday 84 { re: /^yes/i, 85 handler: function() { 86 var d = new Date(); 87 d.setDate(d.getDate() - 1); 88 return d; 89 } 90 }, 91 // 4th 92 { re: /^(\d{1,2})(st|nd|rd|th)?$/i, 93 handler: function(bits) { 94 var d = new Date(); 95 d.setDate(parseInt(bits[1], 10)); 96 return d; 97 } 98 }, 99 // 4th Jan 100 { re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+)$/i, 101 handler: function(bits) { 102 var d = new Date(); 103 d.setDate(1); 104 d.setMonth(parseMonth(bits[2])); 105 d.setDate(parseInt(bits[1], 10)); 106 return d; 107 } 108 }, 109 // 4th Jan 2003 110 { re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+),? (\d{4})$/i, 111 handler: function(bits) { 112 var d = new Date(); 113 d.setDate(1); 114 d.setYear(bits[3]); 115 d.setMonth(parseMonth(bits[2])); 116 d.setDate(parseInt(bits[1], 10)); 117 return d; 118 } 119 }, 120 // Jan 4th 121 { re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?$/i, 122 handler: function(bits) { 123 var d = new Date(); 124 d.setDate(1); 125 d.setMonth(parseMonth(bits[1])); 126 d.setDate(parseInt(bits[2], 10)); 127 return d; 128 } 129 }, 130 // Jan 4th 2003 131 { re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?,? (\d{4})$/i, 132 handler: function(bits) { 133 var d = new Date(); 134 d.setDate(1); 135 d.setYear(bits[3]); 136 d.setMonth(parseMonth(bits[1])); 137 d.setDate(parseInt(bits[2], 10)); 138 return d; 139 } 140 }, 141 // next Tuesday - this is suspect due to weird meaning of "next" 142 { re: /^next (\w+)$/i, 143 handler: function(bits) { 144 var d = new Date(); 145 var day = d.getDay(); 146 var newDay = parseWeekday(bits[1]); 147 var addDays = newDay - day; 148 if (newDay <= day) { 149 addDays += 7; 150 } 151 d.setDate(d.getDate() + addDays); 152 return d; 153 } 154 }, 155 // last Tuesday 156 { re: /^last (\w+)$/i, 157 handler: function(bits) { 158 throw new Error("Not yet implemented"); 159 } 160 }, 161 // mm/dd/yyyy (American style) 162 { re: /(\d{1,2})\/(\d{1,2})\/(\d{4})/, 163 handler: function(bits) { 164 var d = new Date(); 165 d.setDate(1); 166 d.setYear(bits[3]); 167 d.setMonth(parseInt(bits[1], 10) - 1); // Because months indexed from 0 168 d.setDate(parseInt(bits[2], 10)); 169 return d; 170 } 171 }, 172 // yyyy-mm-dd (ISO style) 173 { re: /(\d{4})-(\d{1,2})-(\d{1,2})/, 174 handler: function(bits) { 175 var d = new Date(); 176 d.setDate(1); 177 d.setYear(parseInt(bits[1])); 178 d.setMonth(parseInt(bits[2], 10) - 1); 179 d.setDate(parseInt(bits[3], 10)); 180 return d; 181 } 182 }, 183]; 184 185function parseDateString(s) { 186 for (var i = 0; i < dateParsePatterns.length; i++) { 187 var re = dateParsePatterns[i].re; 188 var handler = dateParsePatterns[i].handler; 189 var bits = re.exec(s); 190 if (bits) { 191 return handler(bits); 192 } 193 } 194 throw new Error("Invalid date string"); 195} 196 197function fmt00(x) { 198 // fmt00: Tags leading zero onto numbers 0 - 9. 199 // Particularly useful for displaying results from Date methods. 200 // 201 if (Math.abs(parseInt(x)) < 10){ 202 x = "0"+ Math.abs(x); 203 } 204 return x; 205} 206 207function parseDateStringISO(s) { 208 try { 209 var d = parseDateString(s); 210 return d.getFullYear() + '-' + (fmt00(d.getMonth() + 1)) + '-' + fmt00(d.getDate()) 211 } 212 catch (e) { return s; } 213} 214function magicDate(input) { 215 var messagespan = input.id + 'Msg'; 216 try { 217 var d = parseDateString(input.value); 218 input.value = d.getFullYear() + '-' + (fmt00(d.getMonth() + 1)) + '-' + 219 fmt00(d.getDate()); 220 input.className = ''; 221 // Human readable date 222 if (document.getElementById(messagespan)) { 223 document.getElementById(messagespan).firstChild.nodeValue = d.toDateString(); 224 document.getElementById(messagespan).className = 'normal'; 225 } 226 } 227 catch (e) { 228 input.className = 'error'; 229 var message = e.message; 230 // Fix for IE6 bug 231 if (message.indexOf('is null or not an object') > -1) { 232 message = 'Invalid date string'; 233 } 234 if (document.getElementById(messagespan)) { 235 document.getElementById(messagespan).firstChild.nodeValue = message; 236 document.getElementById(messagespan).className = 'error'; 237 } 238 } 239}