All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.neat.internal.NumberFormatterImpl.kt Maven / Gradle / Ivy

package neat.internal

import neat.NumberFormatter
import neat.NumberFormatterOptions
import neat.NumberFormatterRawOptions
import neat.toFormatterOptions
import kotlin.jvm.JvmOverloads
import kotlin.math.round

open class NumberFormatterImpl @JvmOverloads constructor(
    override val options: NumberFormatterRawOptions = NumberFormatterOptions()
) : NumberFormatter {
    private fun finalizeDecimals(amount: Double, options: NumberFormatterOptions): String {
        return if (!options.enforceDecimals) {
            if (amount.toString().endsWith(".0")) {
                return amount.toInt().toString()
            }
            amount.toString()
        } else {
            if (amount.toString().endsWith(".0")) {
                val mantisa = "0".repeat(options.decimals)
                return "${amount.toInt()}.$mantisa"
            } else {
                val mantisa = amount.toString().split(".").getOrNull(1)
                if (mantisa == null) {
                    "${amount}.${"0".repeat(options.decimals)}"
                } else {
                    val numberOfDecimals = amount.toString().split(".").getOrElse(1) { "" }.length
                    amount.toString() + "0".repeat(options.decimals - numberOfDecimals)
                }
            }
        }
    }

    override fun format(number: Number): String = if (options.abbreviate == true) {
        val opt = options.toFormatterOptions().copy(
            decimals = options.decimals ?: NumberFormatterOptions.DEFAULT_DECIMALS_ABBREVIATED
        )
        val value = number.toDouble()
        val (postfix, divider) = when {
            value < 1_000 -> "" to 1
            value >= 1_000 && value < 1_000_000 -> "K" to 1_000
            value >= 1_000_000 && value < 1_000_000_000 -> "M" to 1_000_000
            else -> "B" to 1_000_000_000
        }
        val rounded = round(value * opt.rounder / divider) / opt.rounder
        "${opt.prefix}${finalizeDecimals(rounded, opt)}$postfix"
    } else {
        val opt = options.toFormatterOptions().copy(
            decimals = options.decimals ?: NumberFormatterOptions.DEFAULT_DECIMALS_UNABBREVIATED
        )
        val value = round(number.toDouble() * opt.rounder) / opt.rounder
        val splits = value.toString().split('.')
        var characteristic = splits[0]
        var mantisa = splits.getOrElse(1) { "0" }
        mantisa = if (mantisa.toDouble() == 0.0) "" else mantisa
        characteristic = characteristic.toCharArray().toList().reversed()
            .chunked(3).reversed().joinToString(separator = opt.thousandsSeparator) {
                it.reversed().joinToString(separator = "")
            }
        val finalizedValue = finalizeDecimals(value, opt)
        val mts = finalizedValue.split(".").getOrElse(1) { "" }
        if (opt.enforceDecimals && mantisa == "") {
            "${opt.prefix}$characteristic.$mts${opt.postfix}"
        } else if (mantisa == "") {
            "${opt.prefix}$characteristic${opt.postfix}"
        } else {
            "${opt.prefix}$characteristic${opt.decimalSeparator}$mts${opt.postfix}"
        }
    }

    override fun format(number: Double): String = format(number as Number)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy