Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KTLN-899: Format number with thousand separator in Kotlin #1183

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions core-kotlin-modules/core-kotlin-12/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@
<version>1.0.0-SNAPSHOT</version>
</parent>

<dependencies>
<dependency>
<groupId>io.kotest</groupId>
<artifactId>kotest-runner-junit5</artifactId>
<version>${kotest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.kotest</groupId>
<artifactId>kotest-property-jvm</artifactId>
<version>${kotest.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
Expand All @@ -34,4 +49,10 @@
</plugin>
</plugins>
</build>

<properties>
<kotest.version>5.9.0</kotest.version>
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
</properties>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.baeldung.formatting

import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.*

/**
* Interface for the different formatting implementation.
*/
interface NumberFormat {

/**
* Returns provided number as string with thousands separator.
*/
fun formatted(number: Int): String
}

object FormatByDecimalFormat : NumberFormat {
override fun formatted(number: Int): String =
DecimalFormat("#,###")
.format(number)
.replace(",", ".")
}

object FormatByDecimalFormatGermany : NumberFormat {
override fun formatted(number: Int): String =
DecimalFormat("#,###", DecimalFormatSymbols(Locale.GERMANY))
.format(number)
}

object FormatByStringFormat : NumberFormat {
override fun formatted(number: Int): String =
String.format(Locale.GERMANY, "%,d", number)
}

object FormatByChunking : NumberFormat {
override fun formatted(number: Int): String =
number.toString()
.reversed() // 15000 -> 00051
.chunked(3) // [000] [51]
.joinToString(".") // 000.51
.reversed() // 15.000
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.baeldung.formatting

import io.kotest.core.spec.style.ShouldSpec
import io.kotest.property.Arb
import io.kotest.property.arbitrary.positiveInt
import io.kotest.property.checkAll
import org.assertj.core.api.Assertions.assertThat

class NumberFormatUnitTest : ShouldSpec({

// Dynamic generation of tests for each implementation
nameToImplementationPairs.forEach { (name, function) ->

// Property based test (for each implementation)
should("return correctly formatted string with $name implementation") {
checkAll(Arb.positiveInt()) { number ->
var result = function(number)

assertThat(result).containsPattern("^(\\d{1,3}(\\.\\d{3})*|\\d+)$")
assertThat(number.toString()).isEqualTo(result.replace(".", ""))
}
}

givenToExpectedPairs.forEach { (givenNumber, expectedString) ->

// Parameterised; Example based test
should("return '$expectedString' for $givenNumber with $name implementation") {
assertThat(function(givenNumber)).isEqualTo(expectedString)
}
}

}
})

// Examples to check against, with given number and expected string
private val givenToExpectedPairs = listOf(
0 to "0",
12 to "12",
456 to "456",
100_000 to "100.000",
1_234_567 to "1.234.567"
)

// Different implementations of the formatting feature with the display name
private val nameToImplementationPairs = listOf(
"FormatByChunking" to { it: Int -> FormatByChunking.formatted(it) },
"FormatByStringFormat" to { it: Int -> FormatByStringFormat.formatted(it) },
"FormatByDecimalFormatGermany" to { it: Int -> FormatByDecimalFormatGermany.formatted(it) },
"FormatByDecimalFormat" to { it: Int -> FormatByDecimalFormat.formatted(it) }
)