Skip to content

Instantly share code, notes, and snippets.

@alexcmgit
Last active October 15, 2021 16:09
Show Gist options
  • Save alexcmgit/bd92fc5ee05e8595e66b14e9c6e195e5 to your computer and use it in GitHub Desktop.
Save alexcmgit/bd92fc5ee05e8595e66b14e9c6e195e5 to your computer and use it in GitHub Desktop.
import 'dart:math';
String _roundTo(num value, int decimals,
{bool floor = true, bool round = false, bool ceil = false}) {
assert(floor || round || ceil);
final sign = value >= 0 ? 1 : -1;
final current = ((value * pow(10, decimals)) + (sign * 0.001));
final base = (() {
if (floor) return current.floor();
if (round) return current.round();
if (ceil) return current.ceil();
})()!;
return (base / pow(10, decimals)).toStringAsFixed(decimals);
}
String _format(
num value,
double base, {
bool ceil = true,
bool floor = false,
bool round = false,
int fractionDigits = 2,
bool forceFraction = false,
}) {
if (value < base) return '$value';
final minPostfix = base / pow(10, fractionDigits);
final before = value ~/ base;
final rest = value - before * base;
final rounded = _roundTo(
rest / base,
fractionDigits,
ceil: ceil,
floor: floor,
round: round,
);
final decimalValue = '$rounded'.substring(2);
final after = forceFraction || rest >= minPostfix
? '.${decimalValue.padRight(fractionDigits, '0')}'
: '';
return '$before$after';
}
String formatIt(
num value, {
int fractionDigits = 2,
bool floor = true,
bool round = false,
bool ceil = false,
bool forceFraction = false,
}) {
const bases = [1e15, 1e12, 1e9, 1e6, 1e3];
const postfixes = ['Q', 'T', 'B', 'M', 'K'];
if (value < bases.last) return '$value';
for (var i = 0; i < bases.length; i++) {
final base = bases[i], postfix = postfixes[i];
if (value >= base) {
final formatted = _format(
value,
base,
ceil: ceil,
floor: floor,
round: round,
fractionDigits: fractionDigits,
forceFraction: forceFraction,
);
return '$formatted$postfix';
}
}
throw Exception('We can\'t format $value. Max allowed value: ${bases.first}');
}
/// ======================================================
/// format_number_test.dart
/// ======================================================
import 'package:test/test.dart';
void main() {
group('[formatNumber] method', () {
test(
'only int | Fraction Digits = 2 | floor = true | round = false | ceil = false',
() {
final useCases = [
[1000, '1K'],
[10001, '10K'],
[1000000, '1M'],
[1000001, '1M'],
[34567677, '34.56M'],
[48957634, '48.95M'],
[9435643565, '9.43B'],
[10100, '10.10K'],
[1100000, '1.10M'],
[1111111, '1.11M'],
[10011, '10.01K'],
[1010000, '1.01M'],
[123456789, '123.45M'],
[56897845, '56.89M'],
[10100, '10.10K'],
[999, '999'],
[1, '1'],
[10, '10'],
[150, '150'],
[1234567, '1.23M'],
];
for (var i = 0; i < useCases.length; i++) {
expect(formatIt(useCases[i][0] as num), useCases[i][1] as String);
}
});
test(
'only int | Fraction Digits = 1 | floor = true | round = false | ceil = false',
() {
final useCases = [
[1000, '1K'],
[10001, '10K'],
[1000000, '1M'],
[1000001, '1M'],
[34567677, '34.5M'],
[48957634, '48.9M'],
[9435643565, '9.4B'],
[10100, '10.1K'],
[1100000, '1.1M'],
[1111111, '1.1M'],
[10011, '10K'],
[1010000, '1M'],
[123456789, '123.4M'],
[56897845, '56.8M'],
[10100, '10.1K'],
[999, '999'],
[1, '1'],
[10, '10'],
[150, '150'],
[1234567, '1.2M'],
];
for (var i = 0; i < useCases.length; i++) {
expect(
formatIt(
useCases[i][0] as num,
fractionDigits: 1,
),
useCases[i][1] as String,
);
}
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment