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