API date field returns java.time.format.DateTimeParseException: Text could not be parsed

721 Views Asked by At

I have an API endpoint that has a datetime field and I'm unable to parse it correctly. The API is written in C# and I'm not finding much help on how to resolve this:

kotlinx.datetime.DateTimeFormatException: java.time.format.DateTimeParseException: Text '2022-05-02T16:12:52.393538-04:00' could not be parsed, unparsed text found at index 26 at kotlinx.datetime.LocalDateTime$Companion.parse(LocalDateTime.kt:57) at kotlinx.datetime.serializers.LocalDateTimeIso8601Serializer.deserialize(LocalDateTimeSerializers.kt:19) at kotlinx.datetime.serializers.LocalDateTimeIso8601Serializer.deserialize(LocalDateTimeSerializers.kt:13) at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59) at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36) at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43) at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:79) at com.demo.app.http.response.users.UserAccessTokenResponse$$serializer.deserialize(UserAccessTokenResponse.kt:7) at com.demo.app.http.response.users.UserAccessTokenResponse$$serializer.deserialize(UserAccessTokenResponse.kt:7) at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59) at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36) at kotlinx.serialization.json.Json.decodeFromString(Json.kt:100) at io.ktor.serialization.kotlinx.KotlinxSerializationConverter.deserialize(KotlinxSerializationConverter.kt:55) at io.ktor.client.plugins.contentnegotiation.ContentNegotiation$Plugin$install$2.invokeSuspend(ContentNegotiation.kt:135) at io.ktor.client.plugins.contentnegotiation.ContentNegotiation$Plugin$install$2.invoke(Unknown Source:13) at io.ktor.client.plugins.contentnegotiation.ContentNegotiation$Plugin$install$2.invoke(Unknown Source:6) at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123) at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81) at io.ktor.client.HttpClient$4.invokeSuspend(HttpClient.kt:170) at io.ktor.client.HttpClient$4.invoke(Unknown Source:11) at io.ktor.client.HttpClient$4.invoke(Unknown Source:6) at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123) at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81) at io.ktor.util.pipeline.SuspendFunctionGun.proceedWith(SuspendFunctionGun.kt:91) at io.ktor.client.plugins.HttpCallValidator$Companion$install$2.invokeSuspend(HttpCallValidator.kt:140) at io.ktor.client.plugins.HttpCallValidator$Companion$install$2.invoke(Unknown Source:13) at io.ktor.client.plugins.HttpCallValidator$Companion$install$2.invoke(Unknown Source:6) at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123) at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81) at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:101) at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77) at io.ktor.client.call.HttpClientCall.body(HttpClientCall.kt:87) at com.demo.app.http.TokenHttpClient.getToken(TokenHttpClient.kt:144) at com.demo.app.http.TokenHttpClient$getToken$1.invokeSuspend(Unknown Source:15) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:138) at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:112) at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(SuspendFunctionGun.kt:14) at io.ktor.util.pipeline.SuspendFunctionGun$continuation$1.resumeWith(SuspendFunctionGun.kt:62) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46) at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(SuspendFunctionGun.kt:138) at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:112)

I'm not finding a whole lot on this for kotlinx.serialization and this is a major stoppage for me.

here is how my response object looks:

@Serializable
data class UserAccessTokenResponse(
    @SerialName("http_code")
    val httpCode: Int = 200,
    @SerialName("error_response")
    val errorResponse: String? = null,
    @SerialName("access_token")
    val accessToken: String? = null,
    @SerialName("token_type")
    val tokenType: String? = null,
    @SerialName("expires_in")
    val expiresIn: Int = 0,
    @SerialName("refresh_token")
    val refreshToken: String? = null,
    @SerialName("date_created")
    val dateCreated: LocalDateTime? = null,
    @SerialName("was_refreshed")
    val wasRefresh: Boolean = false
)
1

There are 1 best solutions below

1
On BEST ANSWER

It seems the issue is me using the wrong type. Reading the kotlinx-datetime doc it appears they recommend you use Instant and then converting to LocalDateTime when you need to actually use it within your code.