formatAsReadableNumber method

String formatAsReadableNumber({
  1. String? locale,
  2. int decimalDigits = 2,
  3. String? groupingSeparator,
  4. String? decimalSeparator,
  5. bool trimTrailingZeros = false,
})

Formats this number into a readable string with customizable options.

  • locale specifies the locale to use for formatting (e.g., 'en_US', 'de_DE'). If not provided, the default locale of the system will be used.

  • decimalDigits determines the maximum number of decimal places to display. Must be a non-negative integer. Defaults to 2.

  • groupingSeparator sets the character used for grouping digits (e.g., ',', '.', ' '). If not provided, the locale's default grouping separator will be used.

  • decimalSeparator sets the character used for the decimal point (e.g., '.', ','). If not provided, the locale's default decimal separator will be used.

  • trimTrailingZeros if set to true, trailing zeros after the decimal point will be removed. Defaults to false.

Example usage:

double number = 1000000.50;

// Default formatting
String formattedNumber = number.formatAsReadableNumber();
// Output: '1,000,000.50'

// Indian-style formatting with no decimals and trimmed zeros
formattedNumber = number.formatAsReadableNumber(
  locale: 'en_IN',
  decimalDigits: 0,
  trimTrailingZeros: true,
);
// Output: '10,00,000'

// European-style formatting
formattedNumber = number.formatAsReadableNumber(
  locale: 'de_DE',
  groupingSeparator: '.',
  decimalSeparator: ',',
);
// Output: '1.000.000,50'

// Custom separators
formattedNumber = number.formatAsReadableNumber(
  groupingSeparator: ' ',
  decimalSeparator: ',',
);
// Output: '1 000 000,50'

Implementation

String formatAsReadableNumber({
  String? locale,
  int decimalDigits = 2,
  String? groupingSeparator,
  String? decimalSeparator,
  bool trimTrailingZeros = false,
}) {
  // Validate input parameters
  if (decimalDigits < 0) {
    throw ArgumentError('decimalDigits must be non-negative');
  }

  // Create a NumberFormat instance with the specified locale
  final formatter = NumberFormat.decimalPattern(locale)
    // Set the maximum and minimum number of decimal digits
    ..maximumFractionDigits = decimalDigits
    ..minimumFractionDigits = trimTrailingZeros ? 0 : decimalDigits;

  // Store the default separators from the locale
  final defaultGroupingSeparator = formatter.symbols.GROUP_SEP;
  final defaultDecimalSeparator = formatter.symbols.DECIMAL_SEP;

  // Format the number
  var formatted = formatter.format(this);

  // Use a unique placeholder for the decimal separator
  const decimalPlaceholder = '{DECIMAL_PLACEHOLDER}';
  formatted = formatted.replaceFirst(
    defaultDecimalSeparator,
    decimalPlaceholder,
  );

  // Replace grouping separator if a custom one is provided
  if (groupingSeparator != null && groupingSeparator.isNotEmpty) {
    formatted = formatted.replaceAll(
      defaultGroupingSeparator,
      groupingSeparator,
    );
  }

  // Replace the decimal placeholder with the custom decimal separator
  if (decimalSeparator != null && decimalSeparator.isNotEmpty) {
    formatted = formatted.replaceFirst(decimalPlaceholder, decimalSeparator);
  } else {
    // Replace placeholder back to default decimal separator
    formatted = formatted.replaceFirst(
      decimalPlaceholder,
      defaultDecimalSeparator,
    );
  }

  return formatted;
}