Skip to content

Commit f961e99

Browse files
Merge pull request #1183 from LeoHelfferich/BAEL-8537
KTLN-899: Format number with thousand separator in Kotlin
2 parents 32d4da2 + dbc1172 commit f961e99

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

core-kotlin-modules/core-kotlin-12/pom.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@
1414
<version>1.0.0-SNAPSHOT</version>
1515
</parent>
1616

17+
<dependencies>
18+
<dependency>
19+
<groupId>io.kotest</groupId>
20+
<artifactId>kotest-runner-junit5</artifactId>
21+
<version>${kotest.version}</version>
22+
<scope>test</scope>
23+
</dependency>
24+
<dependency>
25+
<groupId>io.kotest</groupId>
26+
<artifactId>kotest-property-jvm</artifactId>
27+
<version>${kotest.version}</version>
28+
<scope>test</scope>
29+
</dependency>
30+
</dependencies>
31+
1732
<build>
1833
<sourceDirectory>src/main/kotlin</sourceDirectory>
1934
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
@@ -34,4 +49,10 @@
3449
</plugin>
3550
</plugins>
3651
</build>
52+
53+
<properties>
54+
<kotest.version>5.9.0</kotest.version>
55+
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
56+
</properties>
57+
3758
</project>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.baeldung.formatting
2+
3+
import java.text.DecimalFormat
4+
import java.text.DecimalFormatSymbols
5+
import java.util.*
6+
7+
/**
8+
* Interface for the different formatting implementation.
9+
*/
10+
interface NumberFormat {
11+
12+
/**
13+
* Returns provided number as string with thousands separator.
14+
*/
15+
fun formatted(number: Int): String
16+
}
17+
18+
object FormatByDecimalFormat : NumberFormat {
19+
override fun formatted(number: Int): String =
20+
DecimalFormat("#,###")
21+
.format(number)
22+
.replace(",", ".")
23+
}
24+
25+
object FormatByDecimalFormatGermany : NumberFormat {
26+
override fun formatted(number: Int): String =
27+
DecimalFormat("#,###", DecimalFormatSymbols(Locale.GERMANY))
28+
.format(number)
29+
}
30+
31+
object FormatByStringFormat : NumberFormat {
32+
override fun formatted(number: Int): String =
33+
String.format(Locale.GERMANY, "%,d", number)
34+
}
35+
36+
object FormatByChunking : NumberFormat {
37+
override fun formatted(number: Int): String =
38+
number.toString()
39+
.reversed() // 15000 -> 00051
40+
.chunked(3) // [000] [51]
41+
.joinToString(".") // 000.51
42+
.reversed() // 15.000
43+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.baeldung.formatting
2+
3+
import io.kotest.core.spec.style.ShouldSpec
4+
import io.kotest.property.Arb
5+
import io.kotest.property.arbitrary.positiveInt
6+
import io.kotest.property.checkAll
7+
import org.assertj.core.api.Assertions.assertThat
8+
9+
class NumberFormatUnitTest : ShouldSpec({
10+
11+
// Dynamic generation of tests for each implementation
12+
nameToImplementationPairs.forEach { (name, function) ->
13+
14+
// Property based test (for each implementation)
15+
should("return correctly formatted string with $name implementation") {
16+
checkAll(Arb.positiveInt()) { number ->
17+
var result = function(number)
18+
19+
assertThat(result).containsPattern("^(\\d{1,3}(\\.\\d{3})*|\\d+)$")
20+
assertThat(number.toString()).isEqualTo(result.replace(".", ""))
21+
}
22+
}
23+
24+
givenToExpectedPairs.forEach { (givenNumber, expectedString) ->
25+
26+
// Parameterised; Example based test
27+
should("return '$expectedString' for $givenNumber with $name implementation") {
28+
assertThat(function(givenNumber)).isEqualTo(expectedString)
29+
}
30+
}
31+
32+
}
33+
})
34+
35+
// Examples to check against, with given number and expected string
36+
private val givenToExpectedPairs = listOf(
37+
0 to "0",
38+
12 to "12",
39+
456 to "456",
40+
100_000 to "100.000",
41+
1_234_567 to "1.234.567"
42+
)
43+
44+
// Different implementations of the formatting feature with the display name
45+
private val nameToImplementationPairs = listOf(
46+
"FormatByChunking" to { it: Int -> FormatByChunking.formatted(it) },
47+
"FormatByStringFormat" to { it: Int -> FormatByStringFormat.formatted(it) },
48+
"FormatByDecimalFormatGermany" to { it: Int -> FormatByDecimalFormatGermany.formatted(it) },
49+
"FormatByDecimalFormat" to { it: Int -> FormatByDecimalFormat.formatted(it) }
50+
)

0 commit comments

Comments
 (0)