Home | History | Annotate | Download | only in sunspider-0.9
      1 /*
      2  * Copyright (C) 2004 Baron Schwartz <baron at sequent dot org>
      3  *
      4  * This program is free software; you can redistribute it and/or modify it
      5  * under the terms of the GNU Lesser General Public License as published by the
      6  * Free Software Foundation, version 2.1.
      7  *
      8  * This program is distributed in the hope that it will be useful, but WITHOUT
      9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     10  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
     11  * details.
     12  */
     13 
     14 Date.parseFunctions = {count:0};
     15 Date.parseRegexes = [];
     16 Date.formatFunctions = {count:0};
     17 
     18 Date.prototype.dateFormat = function(format) {
     19     if (Date.formatFunctions[format] == null) {
     20         Date.createNewFormat(format);
     21     }
     22     var func = Date.formatFunctions[format];
     23     return this[func]();
     24 }
     25 
     26 Date.createNewFormat = function(format) {
     27     var funcName = "format" + Date.formatFunctions.count++;
     28     Date.formatFunctions[format] = funcName;
     29     var code = "Date.prototype." + funcName + " = function(){return ";
     30     var special = false;
     31     var ch = '';
     32     for (var i = 0; i < format.length; ++i) {
     33         ch = format.charAt(i);
     34         if (!special && ch == "\\") {
     35             special = true;
     36         }
     37         else if (special) {
     38             special = false;
     39             code += "'" + String.escape(ch) + "' + ";
     40         }
     41         else {
     42             code += Date.getFormatCode(ch);
     43         }
     44     }
     45     eval(code.substring(0, code.length - 3) + ";}");
     46 }
     47 
     48 Date.getFormatCode = function(character) {
     49     switch (character) {
     50     case "d":
     51         return "String.leftPad(this.getDate(), 2, '0') + ";
     52     case "D":
     53         return "Date.dayNames[this.getDay()].substring(0, 3) + ";
     54     case "j":
     55         return "this.getDate() + ";
     56     case "l":
     57         return "Date.dayNames[this.getDay()] + ";
     58     case "S":
     59         return "this.getSuffix() + ";
     60     case "w":
     61         return "this.getDay() + ";
     62     case "z":
     63         return "this.getDayOfYear() + ";
     64     case "W":
     65         return "this.getWeekOfYear() + ";
     66     case "F":
     67         return "Date.monthNames[this.getMonth()] + ";
     68     case "m":
     69         return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
     70     case "M":
     71         return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
     72     case "n":
     73         return "(this.getMonth() + 1) + ";
     74     case "t":
     75         return "this.getDaysInMonth() + ";
     76     case "L":
     77         return "(this.isLeapYear() ? 1 : 0) + ";
     78     case "Y":
     79         return "this.getFullYear() + ";
     80     case "y":
     81         return "('' + this.getFullYear()).substring(2, 4) + ";
     82     case "a":
     83         return "(this.getHours() < 12 ? 'am' : 'pm') + ";
     84     case "A":
     85         return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
     86     case "g":
     87         return "((this.getHours() %12) ? this.getHours() % 12 : 12) + ";
     88     case "G":
     89         return "this.getHours() + ";
     90     case "h":
     91         return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";
     92     case "H":
     93         return "String.leftPad(this.getHours(), 2, '0') + ";
     94     case "i":
     95         return "String.leftPad(this.getMinutes(), 2, '0') + ";
     96     case "s":
     97         return "String.leftPad(this.getSeconds(), 2, '0') + ";
     98     case "O":
     99         return "this.getGMTOffset() + ";
    100     case "T":
    101         return "this.getTimezone() + ";
    102     case "Z":
    103         return "(this.getTimezoneOffset() * -60) + ";
    104     default:
    105         return "'" + String.escape(character) + "' + ";
    106     }
    107 }
    108 
    109 Date.parseDate = function(input, format) {
    110     if (Date.parseFunctions[format] == null) {
    111         Date.createParser(format);
    112     }
    113     var func = Date.parseFunctions[format];
    114     return Date[func](input);
    115 }
    116 
    117 Date.createParser = function(format) {
    118     var funcName = "parse" + Date.parseFunctions.count++;
    119     var regexNum = Date.parseRegexes.length;
    120     var currentGroup = 1;
    121     Date.parseFunctions[format] = funcName;
    122 
    123     var code = "Date." + funcName + " = function(input){\n"
    124         + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n"
    125         + "var d = new Date();\n"
    126         + "y = d.getFullYear();\n"
    127         + "m = d.getMonth();\n"
    128         + "d = d.getDate();\n"
    129         + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
    130         + "if (results && results.length > 0) {"
    131     var regex = "";
    132 
    133     var special = false;
    134     var ch = '';
    135     for (var i = 0; i < format.length; ++i) {
    136         ch = format.charAt(i);
    137         if (!special && ch == "\\") {
    138             special = true;
    139         }
    140         else if (special) {
    141             special = false;
    142             regex += String.escape(ch);
    143         }
    144         else {
    145             obj = Date.formatCodeToRegex(ch, currentGroup);
    146             currentGroup += obj.g;
    147             regex += obj.s;
    148             if (obj.g && obj.c) {
    149                 code += obj.c;
    150             }
    151         }
    152     }
    153 
    154     code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
    155         + "{return new Date(y, m, d, h, i, s);}\n"
    156         + "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
    157         + "{return new Date(y, m, d, h, i);}\n"
    158         + "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n"
    159         + "{return new Date(y, m, d, h);}\n"
    160         + "else if (y > 0 && m >= 0 && d > 0)\n"
    161         + "{return new Date(y, m, d);}\n"
    162         + "else if (y > 0 && m >= 0)\n"
    163         + "{return new Date(y, m);}\n"
    164         + "else if (y > 0)\n"
    165         + "{return new Date(y);}\n"
    166         + "}return null;}";
    167 
    168     Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
    169     eval(code);
    170 }
    171 
    172 Date.formatCodeToRegex = function(character, currentGroup) {
    173     switch (character) {
    174     case "D":
    175         return {g:0,
    176         c:null,
    177         s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
    178     case "j":
    179     case "d":
    180         return {g:1,
    181             c:"d = parseInt(results[" + currentGroup + "], 10);\n",
    182             s:"(\\d{1,2})"};
    183     case "l":
    184         return {g:0,
    185             c:null,
    186             s:"(?:" + Date.dayNames.join("|") + ")"};
    187     case "S":
    188         return {g:0,
    189             c:null,
    190             s:"(?:st|nd|rd|th)"};
    191     case "w":
    192         return {g:0,
    193             c:null,
    194             s:"\\d"};
    195     case "z":
    196         return {g:0,
    197             c:null,
    198             s:"(?:\\d{1,3})"};
    199     case "W":
    200         return {g:0,
    201             c:null,
    202             s:"(?:\\d{2})"};
    203     case "F":
    204         return {g:1,
    205             c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
    206             s:"(" + Date.monthNames.join("|") + ")"};
    207     case "M":
    208         return {g:1,
    209             c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
    210             s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
    211     case "n":
    212     case "m":
    213         return {g:1,
    214             c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
    215             s:"(\\d{1,2})"};
    216     case "t":
    217         return {g:0,
    218             c:null,
    219             s:"\\d{1,2}"};
    220     case "L":
    221         return {g:0,
    222             c:null,
    223             s:"(?:1|0)"};
    224     case "Y":
    225         return {g:1,
    226             c:"y = parseInt(results[" + currentGroup + "], 10);\n",
    227             s:"(\\d{4})"};
    228     case "y":
    229         return {g:1,
    230             c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
    231                 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
    232             s:"(\\d{1,2})"};
    233     case "a":
    234         return {g:1,
    235             c:"if (results[" + currentGroup + "] == 'am') {\n"
    236                 + "if (h == 12) { h = 0; }\n"
    237                 + "} else { if (h < 12) { h += 12; }}",
    238             s:"(am|pm)"};
    239     case "A":
    240         return {g:1,
    241             c:"if (results[" + currentGroup + "] == 'AM') {\n"
    242                 + "if (h == 12) { h = 0; }\n"
    243                 + "} else { if (h < 12) { h += 12; }}",
    244             s:"(AM|PM)"};
    245     case "g":
    246     case "G":
    247     case "h":
    248     case "H":
    249         return {g:1,
    250             c:"h = parseInt(results[" + currentGroup + "], 10);\n",
    251             s:"(\\d{1,2})"};
    252     case "i":
    253         return {g:1,
    254             c:"i = parseInt(results[" + currentGroup + "], 10);\n",
    255             s:"(\\d{2})"};
    256     case "s":
    257         return {g:1,
    258             c:"s = parseInt(results[" + currentGroup + "], 10);\n",
    259             s:"(\\d{2})"};
    260     case "O":
    261         return {g:0,
    262             c:null,
    263             s:"[+-]\\d{4}"};
    264     case "T":
    265         return {g:0,
    266             c:null,
    267             s:"[A-Z]{3}"};
    268     case "Z":
    269         return {g:0,
    270             c:null,
    271             s:"[+-]\\d{1,5}"};
    272     default:
    273         return {g:0,
    274             c:null,
    275             s:String.escape(character)};
    276     }
    277 }
    278 
    279 Date.prototype.getTimezone = function() {
    280     return this.toString().replace(
    281         /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace(
    282         /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
    283 }
    284 
    285 Date.prototype.getGMTOffset = function() {
    286     return (this.getTimezoneOffset() > 0 ? "-" : "+")
    287         + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0")
    288         + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
    289 }
    290 
    291 Date.prototype.getDayOfYear = function() {
    292     var num = 0;
    293     Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
    294     for (var i = 0; i < this.getMonth(); ++i) {
    295         num += Date.daysInMonth[i];
    296     }
    297     return num + this.getDate() - 1;
    298 }
    299 
    300 Date.prototype.getWeekOfYear = function() {
    301     // Skip to Thursday of this week
    302     var now = this.getDayOfYear() + (4 - this.getDay());
    303     // Find the first Thursday of the year
    304     var jan1 = new Date(this.getFullYear(), 0, 1);
    305     var then = (7 - jan1.getDay() + 4);
    306     document.write(then);
    307     return String.leftPad(((now - then) / 7) + 1, 2, "0");
    308 }
    309 
    310 Date.prototype.isLeapYear = function() {
    311     var year = this.getFullYear();
    312     return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
    313 }
    314 
    315 Date.prototype.getFirstDayOfMonth = function() {
    316     var day = (this.getDay() - (this.getDate() - 1)) % 7;
    317     return (day < 0) ? (day + 7) : day;
    318 }
    319 
    320 Date.prototype.getLastDayOfMonth = function() {
    321     var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
    322     return (day < 0) ? (day + 7) : day;
    323 }
    324 
    325 Date.prototype.getDaysInMonth = function() {
    326     Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
    327     return Date.daysInMonth[this.getMonth()];
    328 }
    329 
    330 Date.prototype.getSuffix = function() {
    331     switch (this.getDate()) {
    332         case 1:
    333         case 21:
    334         case 31:
    335             return "st";
    336         case 2:
    337         case 22:
    338             return "nd";
    339         case 3:
    340         case 23:
    341             return "rd";
    342         default:
    343             return "th";
    344     }
    345 }
    346 
    347 String.escape = function(string) {
    348     return string.replace(/('|\\)/g, "\\$1");
    349 }
    350 
    351 String.leftPad = function (val, size, ch) {
    352     var result = new String(val);
    353     if (ch == null) {
    354         ch = " ";
    355     }
    356     while (result.length < size) {
    357         result = ch + result;
    358     }
    359     return result;
    360 }
    361 
    362 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
    363 Date.monthNames =
    364    ["January",
    365     "February",
    366     "March",
    367     "April",
    368     "May",
    369     "June",
    370     "July",
    371     "August",
    372     "September",
    373     "October",
    374     "November",
    375     "December"];
    376 Date.dayNames =
    377    ["Sunday",
    378     "Monday",
    379     "Tuesday",
    380     "Wednesday",
    381     "Thursday",
    382     "Friday",
    383     "Saturday"];
    384 Date.y2kYear = 50;
    385 Date.monthNumbers = {
    386     Jan:0,
    387     Feb:1,
    388     Mar:2,
    389     Apr:3,
    390     May:4,
    391     Jun:5,
    392     Jul:6,
    393     Aug:7,
    394     Sep:8,
    395     Oct:9,
    396     Nov:10,
    397     Dec:11};
    398 Date.patterns = {
    399     ISO8601LongPattern:"Y-m-d H:i:s",
    400     ISO8601ShortPattern:"Y-m-d",
    401     ShortDatePattern: "n/j/Y",
    402     LongDatePattern: "l, F d, Y",
    403     FullDateTimePattern: "l, F d, Y g:i:s A",
    404     MonthDayPattern: "F d",
    405     ShortTimePattern: "g:i A",
    406     LongTimePattern: "g:i:s A",
    407     SortableDateTimePattern: "Y-m-d\\TH:i:s",
    408     UniversalSortableDateTimePattern: "Y-m-d H:i:sO",
    409     YearMonthPattern: "F, Y"};
    410 
    411 var date = new Date("1/1/2007 1:11:11");
    412 
    413 for (i = 0; i < 4000; ++i) {
    414     var shortFormat = date.dateFormat("Y-m-d");
    415     var longFormat = date.dateFormat("l, F d, Y g:i:s A");
    416     date.setTime(date.getTime() + 84266956);
    417 }
    418