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 7 cr.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