@@ -12,13 +12,11 @@ import kotlinx.datetime.internal.*
12
12
import kotlinx.datetime.serializers.InstantIso8601Serializer
13
13
import kotlinx.serialization.Serializable
14
14
import java.time.DateTimeException
15
- import java.time.format.DateTimeParseException
16
- import java.time.temporal.ChronoUnit
15
+ import java.time.temporal.*
17
16
import kotlin.time.*
18
17
import kotlin.time.Duration.Companion.nanoseconds
19
18
import kotlin.time.Duration.Companion.seconds
20
19
import java.time.Instant as jtInstant
21
- import java.time.OffsetDateTime as jtOffsetDateTime
22
20
import java.time.Clock as jtClock
23
21
24
22
@Serializable(with = InstantIso8601Serializer ::class )
@@ -67,35 +65,23 @@ public actual class Instant internal constructor(internal val value: jtInstant)
67
65
public actual fun fromEpochMilliseconds (epochMilliseconds : Long ): Instant =
68
66
Instant (jtInstant.ofEpochMilli(epochMilliseconds))
69
67
70
- public actual fun parse (input : CharSequence , format : DateTimeFormat <DateTimeComponents >): Instant =
71
- if (format == = DateTimeComponents .Formats .ISO_DATE_TIME_OFFSET ) {
72
- try {
73
- Instant (jtOffsetDateTime.parse(fixOffsetRepresentation(input)).toInstant())
74
- } catch (e: DateTimeParseException ) {
75
- throw DateTimeFormatException (e)
76
- }
77
- } else {
78
- try {
79
- format.parse(input).toInstantUsingOffset()
80
- } catch (e: IllegalArgumentException ) {
81
- throw DateTimeFormatException (" Failed to parse an instant from '$input '" , e)
82
- }
83
- }
68
+ // TODO: implement a custom parser to 1) help DCE get rid of the formatting machinery 2) move Instant to stdlib
69
+ public actual fun parse (input : CharSequence , format : DateTimeFormat <DateTimeComponents >): Instant = try {
70
+ /* *
71
+ * Can't use built-in Java Time's handling of `Instant.parse` because it supports 24:00:00 and
72
+ * 23:59:60, and also doesn't support non-`Z` UTC offsets on older JDKs.
73
+ * Can't use custom Java Time's formats because Java 8 doesn't support the UTC offset format with
74
+ * optional minutes and seconds and `:` between them:
75
+ * https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatterBuilder.html#appendOffset-java.lang.String-java.lang.String-
76
+ */
77
+ format.parse(input).toInstantUsingOffset()
78
+ } catch (e: IllegalArgumentException ) {
79
+ throw DateTimeFormatException (" Failed to parse an instant from '$input '" , e)
80
+ }
84
81
85
82
@Deprecated(" This overload is only kept for binary compatibility" , level = DeprecationLevel .HIDDEN )
86
83
public fun parse (isoString : String ): Instant = parse(input = isoString)
87
84
88
- /* * A workaround for a quirk of the JDKs older than 11 where the string representations of Instant that have an
89
- * offset of the form "+XX" are not recognized by [jtOffsetDateTime.parse], while "+XX:XX" work fine. */
90
- private fun fixOffsetRepresentation (isoString : CharSequence ): CharSequence {
91
- val time = isoString.indexOf(' T' , ignoreCase = true )
92
- if (time == - 1 ) return isoString // the string is malformed
93
- val offset = isoString.indexOfLast { c -> c == ' +' || c == ' -' }
94
- if (offset < time) return isoString // the offset is 'Z' and not +/- something else
95
- val separator = isoString.indexOf(' :' , offset) // if there is a ':' in the offset, no changes needed
96
- return if (separator != - 1 ) isoString else " $isoString :00"
97
- }
98
-
99
85
public actual fun fromEpochSeconds (epochSeconds : Long , nanosecondAdjustment : Long ): Instant = try {
100
86
Instant (jtInstant.ofEpochSecond(epochSeconds, nanosecondAdjustment))
101
87
} catch (e: Exception ) {
0 commit comments