Skip to content

Commit af881b4

Browse files
committed
Support LocalDateFormat.appendMonthName
1 parent 720b97d commit af881b4

File tree

3 files changed

+66
-9
lines changed

3 files changed

+66
-9
lines changed

core/common/src/internal/format/FieldFormatDirective.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ internal interface FieldFormatDirective<in Target> {
4242
*/
4343
internal abstract class UnsignedIntFieldFormatDirective<in Target>(
4444
final override val field: UnsignedFieldSpec<Target>,
45-
val minDigits: Int,
45+
private val minDigits: Int,
4646
) : FieldFormatDirective<Target> {
4747

4848
final override val signGetter: ((Target) -> Int)? = null
4949

50-
val maxDigits: Int = field.maxDigits
50+
private val maxDigits: Int = field.maxDigits
5151

5252
init {
5353
require(minDigits >= 0)
@@ -96,11 +96,19 @@ internal abstract class NamedUnsignedIntFieldFormatDirective<in Target>(
9696

9797
final override val signGetter: ((Target) -> Int)? = null
9898

99+
private fun getStringValue(target: Target): String = values[field.getNotNull(target) - field.minValue]
100+
101+
private fun setStringValue(target: Target, value: String) {
102+
field.setWithoutReassigning(target, values.indexOf(value) + field.minValue)
103+
}
104+
99105
override fun formatter(): FormatterOperation<Target> =
100-
TODO()
106+
StringFormatterOperation(::getStringValue)
101107

102108
override fun parser(signsInverted: Boolean): ParserStructure<Target> =
103-
TODO()
109+
ParserStructure(listOf(
110+
StringSetParserOperation(values, ::setStringValue, "One of $values for ${field.name}")
111+
), emptyList())
104112
}
105113

106114
internal abstract class StringFieldFormatDirective<in Target>(

core/common/src/internal/format/parser/ParserOperation.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,12 @@ internal class NumberSpanParserOperation<Output>(
106106
* Matches the longest suitable string from `strings` and calls [consume] with the matched string.
107107
*/
108108
internal class StringSetParserOperation<Output>(
109-
strings: Set<String>,
109+
strings: Collection<String>,
110110
private val setter: (Output, String) -> Unit,
111-
private val whatThisExpects: String
112-
) :
113-
ParserOperation<Output> {
111+
private val whatThisExpects: String,
112+
) : ParserOperation<Output> {
113+
114+
// TODO: tries don't have good performance characteristics for small sets, add a special case for small sets
114115

115116
private class TrieNode(
116117
val children: MutableList<Pair<String, TrieNode>> = mutableListOf(),
@@ -125,7 +126,7 @@ internal class StringSetParserOperation<Output>(
125126
for (char in string) {
126127
val searchResult = node.children.binarySearchBy(char.toString()) { it.first }
127128
node = if (searchResult < 0) {
128-
TrieNode().also { node.children.add(-searchResult + 1, char.toString() to it) }
129+
TrieNode().also { node.children.add(-searchResult - 1, char.toString() to it) }
129130
} else {
130131
node.children[searchResult].second
131132
}

core/common/test/format/DateFormatTest.kt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,54 @@ class DateFormatTest {
8484
}, dates)
8585
}
8686

87+
@Test
88+
fun testDayMonthNameYear() {
89+
val dates = buildMap<LocalDate, Pair<String, Set<String>>> {
90+
put(LocalDate(2008, 7, 5), ("05 July 2008" to setOf()))
91+
put(LocalDate(2007, 12, 31), ("31 December 2007" to setOf()))
92+
put(LocalDate(999, 11, 30), ("30 November 0999" to setOf()))
93+
put(LocalDate(-1, 1, 2), ("02 January -0001" to setOf()))
94+
put(LocalDate(9999, 10, 31), ("31 October 9999" to setOf()))
95+
put(LocalDate(-9999, 9, 30), ("30 September -9999" to setOf()))
96+
put(LocalDate(10000, 8, 1), ("01 August 10000" to setOf()))
97+
put(LocalDate(-10000, 7, 1), ("01 July -10000" to setOf()))
98+
put(LocalDate(123456, 6, 1), ("01 June 123456" to setOf()))
99+
put(LocalDate(-123456, 5, 1), ("01 May -123456" to setOf()))
100+
}
101+
val format = LocalDateFormat.build {
102+
appendDayOfMonth(2)
103+
appendLiteral(' ')
104+
appendMonthName(listOf("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"))
105+
appendLiteral(' ')
106+
appendYear(4)
107+
}
108+
test(format, dates)
109+
}
110+
111+
@Test
112+
fun testRomanNumerals() {
113+
val dates = buildMap<LocalDate, Pair<String, Set<String>>> {
114+
put(LocalDate(2008, 7, 5), ("05 VII 2008" to setOf()))
115+
put(LocalDate(2007, 12, 31), ("31 XII 2007" to setOf()))
116+
put(LocalDate(999, 11, 30), ("30 XI 999" to setOf()))
117+
put(LocalDate(-1, 1, 2), ("02 I -1" to setOf()))
118+
put(LocalDate(9999, 10, 31), ("31 X 9999" to setOf()))
119+
put(LocalDate(-9999, 9, 30), ("30 IX -9999" to setOf()))
120+
put(LocalDate(10000, 8, 1), ("01 VIII 10000" to setOf()))
121+
put(LocalDate(-10000, 7, 1), ("01 VII -10000" to setOf()))
122+
put(LocalDate(123456, 6, 1), ("01 VI 123456" to setOf()))
123+
put(LocalDate(-123456, 5, 1), ("01 V -123456" to setOf()))
124+
}
125+
val format = LocalDateFormat.build {
126+
appendDayOfMonth(2)
127+
appendLiteral(' ')
128+
appendMonthName(listOf("I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"))
129+
appendLiteral(' ')
130+
appendYear()
131+
}
132+
test(format, dates)
133+
}
134+
87135
private fun test(format: LocalDateFormat, strings: Map<LocalDate, Pair<String, Set<String>>>) {
88136
for ((date, stringsForDate) in strings) {
89137
val (canonicalString, otherStrings) = stringsForDate

0 commit comments

Comments
 (0)