• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// TODO(rginda): Fill out formatTime, add testcases.
6
7cr.define('cr', function() {
8
9  /**
10   * Lookup tables used by bytesToSi.
11   */
12  var units = ['B', 'k', 'M', 'G', 'T', 'P'];
13  var scale = [1, 1e3, 1e6, 1e9, 1e12, 1e15];
14
15  /**
16   * Construct a new Locale object with a set of strings.
17   *
18   * The strings object maps symbolic string names to translated strings
19   * for the locale.  Lists of translated strings are delimited with the caret
20   * ('^') character.
21   *
22   *  LOCALE_DAYS_SHORT: List of abbreviated day names.
23   *  LOCALE_MONTHS_SHORT: List of abbreviated month names.
24   *  LOCALE_FMT_SHORT_DATE: A Locale.prototype.formatTime format specifier
25   *      representing the short date format (e.g. Apr 1, 2011) for the
26   *      locale.
27   */
28  function Locale(strings) {
29    this.dateStrings_ = {
30      dayShort: strings.LOCALE_DAYS_SHORT.split('^'),
31      monthShort: strings.LOCALE_MONTHS_SHORT.split('^'),
32      shortDateFormat: strings.LOCALE_FMT_DATE_SHORT
33    };
34  }
35
36  Locale.prototype = {
37    /**
38     * Convert a number of bytes into an appropriate International System of
39     * Units (SI) representation, using the correct number separators.
40     *
41     * The first time this function is called it computes a lookup table which
42     * is cached for subsequent calls.
43     *
44     * @param {number} bytes The number of bytes.
45     */
46    bytesToSi: function(bytes) {
47      function fmt(s, u) {
48        var rounded = Math.round(bytes / s * 10) / 10;
49        return rounded.toLocaleString() + u;
50      }
51
52      // This loop index is used outside the loop if it turns out |bytes|
53      // requires the largest unit.
54      var i;
55
56      for (i = 0; i < units.length - 1; i++) {
57        if (bytes < scale[i + 1])
58          return fmt(scale[i], units[i]);
59      }
60
61      return fmt(scale[i], units[i]);
62    },
63
64    /**
65     * Format a date as a string using the given format specifier.
66     *
67     * This function is similar to strftime() from the C standard library, with
68     * the GNU extensions for controlling padding.
69     *
70     * The following conversion specifiers are defined:
71     *
72     *  %% - A literal '%'
73     *  %a - The localized abbreviated weekday name.
74     *  %b - The localized abbreviated month name.
75     *  %d - The day of the month, zero padded (01-31).
76     *  %Y - The four digit year.
77     *
78     * Between  the  '%'  character and the conversion specifier character, an
79     * optional flag and field width may be specified.
80     *
81     *  The following flag characters are permitted:
82     *    _  (underscore) Pad a numeric result string with spaces.
83     *    -  (dash) Do not pad a numeric result string.
84     *    ^  Convert alphabetic characters in result string to upper case.
85     *
86     * TODO(rginda): Implement more conversion specifiers.
87     *
88     * @param {Date} date The date to be formatted.
89     * @param {string} spec The format specification.
90     */
91    formatDate: function(date, spec) {
92      var self = this;
93      var strings = this.dateStrings_;
94
95      // Called back once for each conversion specifier.
96      function replaceSpecifier(m, flag, width, code) {
97
98        // Left pad utility.
99        function lpad(value, ch) {
100          value = String(value);
101
102          while (width && value.length < width) {
103            value = ch + value;
104          }
105
106          return value;
107        }
108
109        // Format a value according to the selected flag and field width.
110        function fmt(value, defaultWidth) {
111          if (flag == '-')  // No padding.
112            return value;
113
114          if (flag == '^')  // Convert to uppercase.
115            value = String(value).toUpperCase();
116
117          if (typeof width == 'undefined')
118            width = defaultWidth;
119
120          // If there is no width specifier, there's nothing to pad.
121          if (!width)
122            return value;
123
124          if (flag == '_')  // Pad with spaces.
125            return lpad(value, ' ');
126
127          // Autodetect padding character.
128          if (typeof value == 'number')
129            return lpad(value, '0');
130
131          return lpad(value, ' ');
132        }
133
134        switch (code) {
135          case '%': return '%';
136          case 'a': return fmt(strings.dayShort[date.getDay()]);
137          case 'b': return fmt(strings.monthShort[date.getMonth()]);
138          case 'd': return fmt(date.getDate(), 2);
139          case 'Y': return date.getFullYear();
140          default:
141            console.log('Unknown format specifier: ' + code);
142            return m;
143        }
144      }
145
146      // Conversion specifiers start with a '%', optionally contain a
147      // flag and/or field width, followed by a single letter.
148      // e.g. %a, %-d, %2l.
149      return spec.replace(/%([\^\-_])?(\d+)?([%a-z])?/gi, replaceSpecifier);
150    }
151  };
152
153  /**
154   * Storage for the current cr.locale.
155   */
156  var locale = null;
157
158  return {
159    Locale: Locale,
160    get locale() {
161      return locale;
162    },
163    initLocale: function(strings) {
164      locale = new Locale(strings);
165    }
166  };
167});
168