blob: 0ecbee65934ac8bb415f8d9f1d52e504c6a3cd1b [file] [log] [blame]
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file or at
* https://developers.google.com/open-source/licenses/bsd
*/
library charted.locale.format;
import 'dart:math' as math;
import 'package:intl/intl.dart';
import 'package:charted/locale/locale.dart';
import 'package:charted/core/utils.dart';
part 'format/number_format.dart';
part 'format/time_format.dart';
typedef String NumberFormatFunction(num x, [int precision]);
/**
* Returns a new format function with the given string specifier.
* The format specifier is modeled after Python 3.1's built-in format
* specification mini-language.
*
* The general form of a specifier is:
* [​[fill]align][sign][symbol][0][width][,][.precision][type]
*
* @see <a href="http://docs.python.org/release/3.1.3/library/string.html#formatspec">Python format specification mini-language</a>
*/
FormatFunction format(String specifier, [Locale locale]) {
locale ??= new EnUsLocale();
return locale.numberFormat.format(specifier);
}
/*
* Class for computing the SI format prefix for the given value.
*/
class FormatPrefix {
// SI scale units in increments of 1000.
static const List<String> _unitPrefixes = const [
"y",
"z",
"a",
"f",
"p",
"n",
"µ",
"m",
"",
"k",
"M",
"G",
"T",
"P",
"E",
"Z",
"Y"
];
num Function(num) _scale;
String _symbol;
FormatPrefix(num value, [int precision = 0]) {
var i = 0;
if (value < 0) {
value *= -1;
}
if (precision > 0) {
value = _roundToPrecision(value, _formatPrecision(value, precision));
}
// Determining SI scale of the value in increment of 1000.
i = 1 + (1e-12 + math.log(value) / math.LN10).floor();
i = math.max(-24, math.min(24, ((i - 1) / 3).floor() * 3));
i = 8 + (i / 3).floor();
// Sets the scale and symbol of the value.
var k = math.pow(10, (8 - i).abs() * 3);
_scale = i > 8 ? (d) => d / k : (d) => d * k;
_symbol = _unitPrefixes[i];
}
num _formatPrecision(num x, num p) {
return p - (x != 0 ? (math.log(x) / math.LN10).ceil() : 1);
}
/** Returns the value of x rounded to the nth digit. */
num _roundToPrecision(num x, num n) {
return n != 0 ? (x * (n = math.pow(10, n))).round() / n : x.round();
}
/** Returns the SI prefix for the value. */
String get symbol => _symbol;
/** Returns the scale for the value corresponding to the SI prefix. */
num Function(num) get scale => _scale;
}