@@ -8,3 +8,33 @@ package kotlinx.datetime.internal
88internal fun Char.isAsciiDigit (): Boolean = this in ' 0' .. ' 9'
99
1010internal 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