@@ -8,3 +8,33 @@ package kotlinx.datetime.internal
8
8
internal fun Char.isAsciiDigit (): Boolean = this in ' 0' .. ' 9'
9
9
10
10
internal fun Char.asciiDigitToInt (): Int = this - ' 0'
11
+
12
+ /* * Working around the JSR-310 behavior of failing to parse long year numbers even when they start with leading zeros */
13
+ private fun removeLeadingZerosFromLongYearForm (input : String , minStringLengthAfterYear : Int ): String {
14
+ // the smallest string where the issue can occur is "+00000002024", its length is 12
15
+ val failingYearStringLength = 12
16
+ // happy path: the input is too short or the first character is not a sign, so the year is not in the long form
17
+ if (input.length < failingYearStringLength + minStringLengthAfterYear || input[0 ] !in " +-" ) return input
18
+ // the year is in the long form, so we need to remove the leading zeros
19
+ // find the `-` that separates the year from the month
20
+ val yearEnd = input.indexOf(' -' , 1 )
21
+ // if (yearEnd == -1) return input // implied by the next condition
22
+ // if the year is too short, no need to remove the leading zeros, and if the string is malformed, just leave it
23
+ if (yearEnd < failingYearStringLength) return input
24
+ // how many leading zeroes are there?
25
+ var leadingZeros = 0
26
+ while (input[1 + leadingZeros] == ' 0' ) leadingZeros++ // no overflow, we know `-` is there
27
+ // even if we removed all leading zeros, the year would still be too long
28
+ if (yearEnd - leadingZeros >= failingYearStringLength) return input
29
+ // we remove just enough leading zeros to make the year the right length
30
+ // We need the resulting length to be `failYearStringLength - 1`, the current length is `yearEnd`.
31
+ // The difference is `yearEnd - failingYearStringLength + 1` characters to remove.
32
+ // Both the start index and the end index are shifted by 1 because of the sign.
33
+ return input.removeRange(startIndex = 1 , endIndex = yearEnd - failingYearStringLength + 2 )
34
+ }
35
+
36
+ internal fun removeLeadingZerosFromLongYearFormLocalDate (input : String ) =
37
+ removeLeadingZerosFromLongYearForm(input.toString(), 6 ) // 6 = "-01-02".length
38
+
39
+ internal fun removeLeadingZerosFromLongYearFormLocalDateTime (input : String ) =
40
+ removeLeadingZerosFromLongYearForm(input.toString(), 12 ) // 12 = "-01-02T23:59".length
0 commit comments