PageRenderTime 192ms CodeModel.GetById 80ms app.highlight 15ms RepoModel.GetById 75ms app.codeStats 1ms

/django/contrib/admin/media/js/dateparse.js

https://code.google.com/p/mango-py/
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}