toolkit/javascript/d3/src/time/format.js
changeset 47 c0b4a8b5a012
equal deleted inserted replaced
46:efd9c589177a 47:c0b4a8b5a012
       
     1 d3.time.format = function(template) {
       
     2   var n = template.length;
       
     3 
       
     4   function format(date) {
       
     5     var string = [],
       
     6         i = -1,
       
     7         j = 0,
       
     8         c,
       
     9         f;
       
    10     while (++i < n) {
       
    11       if (template.charCodeAt(i) == 37) {
       
    12         string.push(
       
    13             template.substring(j, i),
       
    14             (f = d3_time_formats[c = template.charAt(++i)])
       
    15             ? f(date) : c);
       
    16         j = i + 1;
       
    17       }
       
    18     }
       
    19     string.push(template.substring(j, i));
       
    20     return string.join("");
       
    21   }
       
    22 
       
    23   format.parse = function(string) {
       
    24     var date = new d3_time(1900, 0, 1),
       
    25         i = d3_time_parse(date, template, string, 0);
       
    26     if (i != string.length) return null;
       
    27     if (date.hour12) {
       
    28       var hours = date.getHours() % 12;
       
    29       date.setHours(date.hour12pm ? hours + 12 : hours);
       
    30     }
       
    31     delete date.hour12;
       
    32     delete date.hour12pm;
       
    33     return date;
       
    34   };
       
    35 
       
    36   format.toString = function() {
       
    37     return template;
       
    38   };
       
    39 
       
    40   return format;
       
    41 };
       
    42 
       
    43 function d3_time_parse(date, template, string, j) {
       
    44   var c,
       
    45       p,
       
    46       i = 0,
       
    47       n = template.length,
       
    48       m = string.length;
       
    49   while (i < n) {
       
    50     if (j >= m) return -1;
       
    51     c = template.charCodeAt(i++);
       
    52     if (c == 37) {
       
    53       p = d3_time_parsers[template.charAt(i++)];
       
    54       if (!p || ((j = p(date, string, j)) < 0)) return -1;
       
    55     } else if (c != string.charCodeAt(j++)) {
       
    56       return -1;
       
    57     }
       
    58   }
       
    59   return j;
       
    60 }
       
    61 
       
    62 var d3_time_zfill2 = d3.format("02d"),
       
    63     d3_time_zfill3 = d3.format("03d"),
       
    64     d3_time_zfill4 = d3.format("04d"),
       
    65     d3_time_sfill2 = d3.format("2d");
       
    66 
       
    67 var d3_time_formats = {
       
    68   a: function(d) { return d3_time_weekdays[d.getDay()].substring(0, 3); },
       
    69   A: function(d) { return d3_time_weekdays[d.getDay()]; },
       
    70   b: function(d) { return d3_time_months[d.getMonth()].substring(0, 3); },
       
    71   B: function(d) { return d3_time_months[d.getMonth()]; },
       
    72   c: d3.time.format("%a %b %e %H:%M:%S %Y"),
       
    73   d: function(d) { return d3_time_zfill2(d.getDate()); },
       
    74   e: function(d) { return d3_time_sfill2(d.getDate()); },
       
    75   H: function(d) { return d3_time_zfill2(d.getHours()); },
       
    76   I: function(d) { return d3_time_zfill2(d.getHours() % 12 || 12); },
       
    77   j: d3_time_dayOfYear,
       
    78   L: function(d) { return d3_time_zfill3(d.getMilliseconds()); },
       
    79   m: function(d) { return d3_time_zfill2(d.getMonth() + 1); },
       
    80   M: function(d) { return d3_time_zfill2(d.getMinutes()); },
       
    81   p: function(d) { return d.getHours() >= 12 ? "PM" : "AM"; },
       
    82   S: function(d) { return d3_time_zfill2(d.getSeconds()); },
       
    83   U: d3_time_weekNumberSunday,
       
    84   w: function(d) { return d.getDay(); },
       
    85   W: d3_time_weekNumberMonday,
       
    86   x: d3.time.format("%m/%d/%y"),
       
    87   X: d3.time.format("%H:%M:%S"),
       
    88   y: function(d) { return d3_time_zfill2(d.getFullYear() % 100); },
       
    89   Y: function(d) { return d3_time_zfill4(d.getFullYear() % 10000); },
       
    90   Z: d3_time_zone,
       
    91   "%": function(d) { return "%"; }
       
    92 };
       
    93 
       
    94 var d3_time_parsers = {
       
    95   a: d3_time_parseWeekdayAbbrev,
       
    96   A: d3_time_parseWeekday,
       
    97   b: d3_time_parseMonthAbbrev,
       
    98   B: d3_time_parseMonth,
       
    99   c: d3_time_parseLocaleFull,
       
   100   d: d3_time_parseDay,
       
   101   e: d3_time_parseDay,
       
   102   H: d3_time_parseHour24,
       
   103   I: d3_time_parseHour12,
       
   104   // j: function(d, s, i) { /*TODO day of year [001,366] */ return i; },
       
   105   L: d3_time_parseMilliseconds,
       
   106   m: d3_time_parseMonthNumber,
       
   107   M: d3_time_parseMinutes,
       
   108   p: d3_time_parseAmPm,
       
   109   S: d3_time_parseSeconds,
       
   110   // U: function(d, s, i) { /*TODO week number (sunday) [00,53] */ return i; },
       
   111   // w: function(d, s, i) { /*TODO weekday [0,6] */ return i; },
       
   112   // W: function(d, s, i) { /*TODO week number (monday) [00,53] */ return i; },
       
   113   x: d3_time_parseLocaleDate,
       
   114   X: d3_time_parseLocaleTime,
       
   115   y: d3_time_parseYear,
       
   116   Y: d3_time_parseFullYear
       
   117   // ,
       
   118   // Z: function(d, s, i) { /*TODO time zone */ return i; },
       
   119   // "%": function(d, s, i) { /*TODO literal % */ return i; }
       
   120 };
       
   121 
       
   122 // Note: weekday is validated, but does not set the date.
       
   123 function d3_time_parseWeekdayAbbrev(date, string, i) {
       
   124   return string.substring(i, i += 3).toLowerCase() in d3_time_weekdayAbbrevLookup ? i : -1;
       
   125 }
       
   126 
       
   127 var d3_time_weekdayAbbrevLookup = {
       
   128   sun: 3,
       
   129   mon: 3,
       
   130   tue: 3,
       
   131   wed: 3,
       
   132   thu: 3,
       
   133   fri: 3,
       
   134   sat: 3
       
   135 };
       
   136 
       
   137 // Note: weekday is validated, but does not set the date.
       
   138 function d3_time_parseWeekday(date, string, i) {
       
   139   d3_time_weekdayRe.lastIndex = 0;
       
   140   var n = d3_time_weekdayRe.exec(string.substring(i, i + 10));
       
   141   return n ? i += n[0].length : -1;
       
   142 }
       
   143 
       
   144 var d3_time_weekdayRe = /^(?:Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)/ig;
       
   145 
       
   146 var d3_time_weekdays = [
       
   147   "Sunday",
       
   148   "Monday",
       
   149   "Tuesday",
       
   150   "Wednesday",
       
   151   "Thursday",
       
   152   "Friday",
       
   153   "Saturday"
       
   154 ];
       
   155 
       
   156 function d3_time_parseMonthAbbrev(date, string, i) {
       
   157   var n = d3_time_monthAbbrevLookup[string.substring(i, i += 3).toLowerCase()];
       
   158   return n == null ? -1 : (date.setMonth(n), i);
       
   159 }
       
   160 
       
   161 var d3_time_monthAbbrevLookup = {
       
   162   jan: 0,
       
   163   feb: 1,
       
   164   mar: 2,
       
   165   apr: 3,
       
   166   may: 4,
       
   167   jun: 5,
       
   168   jul: 6,
       
   169   aug: 7,
       
   170   sep: 8,
       
   171   oct: 9,
       
   172   nov: 10,
       
   173   dec: 11
       
   174 };
       
   175 
       
   176 function d3_time_parseMonth(date, string, i) {
       
   177   d3_time_monthRe.lastIndex = 0;
       
   178   var n = d3_time_monthRe.exec(string.substring(i, i + 12));
       
   179   return n ? (date.setMonth(d3_time_monthLookup[n[0].toLowerCase()]), i += n[0].length) : -1;
       
   180 }
       
   181 
       
   182 var d3_time_monthRe = /^(?:January|February|March|April|May|June|July|August|September|October|November|December)/ig;
       
   183 
       
   184 var d3_time_monthLookup = {
       
   185   january: 0,
       
   186   february: 1,
       
   187   march: 2,
       
   188   april: 3,
       
   189   may: 4,
       
   190   june: 5,
       
   191   july: 6,
       
   192   august: 7,
       
   193   september: 8,
       
   194   october: 9,
       
   195   november: 10,
       
   196   december: 11
       
   197 };
       
   198 
       
   199 var d3_time_months = [
       
   200   "January",
       
   201   "February",
       
   202   "March",
       
   203   "April",
       
   204   "May",
       
   205   "June",
       
   206   "July",
       
   207   "August",
       
   208   "September",
       
   209   "October",
       
   210   "November",
       
   211   "December"
       
   212 ];
       
   213 
       
   214 function d3_time_parseLocaleFull(date, string, i) {
       
   215   return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
       
   216 }
       
   217 
       
   218 function d3_time_parseLocaleDate(date, string, i) {
       
   219   return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
       
   220 }
       
   221 
       
   222 function d3_time_parseLocaleTime(date, string, i) {
       
   223   return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
       
   224 }
       
   225 
       
   226 function d3_time_parseFullYear(date, string, i) {
       
   227   d3_time_numberRe.lastIndex = 0;
       
   228   var n = d3_time_numberRe.exec(string.substring(i, i + 4));
       
   229   return n ? (date.setFullYear(n[0]), i += n[0].length) : -1;
       
   230 }
       
   231 
       
   232 function d3_time_parseYear(date, string, i) {
       
   233   d3_time_numberRe.lastIndex = 0;
       
   234   var n = d3_time_numberRe.exec(string.substring(i, i + 2));
       
   235   return n ? (date.setFullYear(d3_time_century() + +n[0]), i += n[0].length) : -1;
       
   236 }
       
   237 
       
   238 function d3_time_century() {
       
   239   return ~~(new Date().getFullYear() / 1000) * 1000;
       
   240 }
       
   241 
       
   242 function d3_time_parseMonthNumber(date, string, i) {
       
   243   d3_time_numberRe.lastIndex = 0;
       
   244   var n = d3_time_numberRe.exec(string.substring(i, i + 2));
       
   245   return n ? (date.setMonth(n[0] - 1), i += n[0].length) : -1;
       
   246 }
       
   247 
       
   248 function d3_time_parseDay(date, string, i) {
       
   249   d3_time_numberRe.lastIndex = 0;
       
   250   var n = d3_time_numberRe.exec(string.substring(i, i + 2));
       
   251   return n ? (date.setDate(+n[0]), i += n[0].length) : -1;
       
   252 }
       
   253 
       
   254 // Note: we don't validate that the hour is in the range [0,23].
       
   255 function d3_time_parseHour24(date, string, i) {
       
   256   d3_time_numberRe.lastIndex = 0;
       
   257   var n = d3_time_numberRe.exec(string.substring(i, i + 2));
       
   258   return n ? (date.setHours(+n[0]), i += n[0].length) : -1;
       
   259 }
       
   260 
       
   261 // Note: we don't validate that the hour is in the range [1,12].
       
   262 function d3_time_parseHour12(date, string, i) {
       
   263   date.hour12 = true;
       
   264   return d3_time_parseHour24(date, string, i);
       
   265 }
       
   266 
       
   267 function d3_time_parseMinutes(date, string, i) {
       
   268   d3_time_numberRe.lastIndex = 0;
       
   269   var n = d3_time_numberRe.exec(string.substring(i, i + 2));
       
   270   return n ? (date.setMinutes(+n[0]), i += n[0].length) : -1;
       
   271 }
       
   272 
       
   273 function d3_time_parseSeconds(date, string, i) {
       
   274   d3_time_numberRe.lastIndex = 0;
       
   275   var n = d3_time_numberRe.exec(string.substring(i, i + 2));
       
   276   return n ? (date.setSeconds(+n[0]), i += n[0].length) : -1;
       
   277 }
       
   278 
       
   279 function d3_time_parseMilliseconds(date, string, i) {
       
   280   d3_time_numberRe.lastIndex = 0;
       
   281   var n = d3_time_numberRe.exec(string.substring(i, i + 3));
       
   282   return n ? (date.setMilliseconds(+n[0]), i += n[0].length) : -1;
       
   283 }
       
   284 
       
   285 // Note: we don't look at the next directive.
       
   286 var d3_time_numberRe = /\s*\d+/;
       
   287 
       
   288 function d3_time_parseAmPm(date, string, i) {
       
   289   var n = d3_time_amPmLookup[string.substring(i, i += 2).toLowerCase()];
       
   290   return n == null ? -1 : (date.hour12pm = n, i);
       
   291 }
       
   292 
       
   293 var d3_time_amPmLookup = {
       
   294   am: 0,
       
   295   pm: 1
       
   296 };
       
   297 
       
   298 function d3_time_year(d) {
       
   299   return new d3_time(d.getFullYear(), 0, 1);
       
   300 }
       
   301 
       
   302 function d3_time_daysElapsed(d0, d1) {
       
   303   return ~~((d1 - d0) / 864e5 - (d1.getTimezoneOffset() - d0.getTimezoneOffset()) / 1440);
       
   304 }
       
   305 
       
   306 function d3_time_dayOfYear(d) {
       
   307   return d3_time_zfill3(1 + d3_time_daysElapsed(d3_time_year(d), d));
       
   308 }
       
   309 
       
   310 function d3_time_weekNumberSunday(d) {
       
   311   var d0 = d3_time_year(d);
       
   312   return d3_time_zfill2(~~((d3_time_daysElapsed(d0, d) + d0.getDay()) / 7));
       
   313 }
       
   314 
       
   315 function d3_time_weekNumberMonday(d) {
       
   316   var d0 = d3_time_year(d);
       
   317   return d3_time_zfill2(~~((d3_time_daysElapsed(d0, d) + (d0.getDay() + 6) % 7) / 7));
       
   318 }
       
   319 
       
   320 // TODO table of time zone offset names?
       
   321 function d3_time_zone(d) {
       
   322   var z = d.getTimezoneOffset(),
       
   323       zs = z > 0 ? "-" : "+",
       
   324       zh = ~~(Math.abs(z) / 60),
       
   325       zm = Math.abs(z) % 60;
       
   326   return zs + d3_time_zfill2(zh) + d3_time_zfill2(zm);
       
   327 }