Handle JSON Date and Time Fields in Kotlin

Learn how to deserialize JSON date strings into Kotlin's kotlinx-datetime or java.time types. Covers ISO 8601 parsing, custom formats, timezone handling, and serializer setup.

Real-World Patterns

Detailed Explanation

JSON Date/Time Handling in Kotlin

JSON represents dates as strings (typically ISO 8601). Kotlin has multiple options for parsing these, depending on your platform and libraries.

Example JSON

{
  "id": 42,
  "title": "Deploy v2.0",
  "createdAt": "2024-06-15T09:30:00Z",
  "updatedAt": "2024-06-15T14:22:33+09:00",
  "dueDate": "2024-07-01"
}

Option 1: kotlinx-datetime (Multiplatform)

import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDate

@Serializable
data class Task(
    val id: Int,
    val title: String,
    val createdAt: Instant,
    val updatedAt: Instant,
    val dueDate: LocalDate
)

kotlinx-datetime types have built-in serializers, so no extra setup is needed. Instant handles ISO 8601 with timezone, and LocalDate handles date-only strings.

Option 2: java.time (JVM only)

import java.time.Instant
import java.time.LocalDate

data class Task(
    val id: Int,
    val title: String,
    val createdAt: Instant,
    val updatedAt: Instant,
    val dueDate: LocalDate
)

Requires a custom serializer for kotlinx.serialization:

object InstantSerializer : KSerializer<Instant> {
    override val descriptor = PrimitiveSerialDescriptor("Instant", PrimitiveKind.STRING)
    override fun serialize(encoder: Encoder, value: Instant) =
        encoder.encodeString(value.toString())
    override fun deserialize(decoder: Decoder): Instant =
        Instant.parse(decoder.decodeString())
}

Option 3: String with Manual Parsing

data class Task(
    val id: Int,
    val title: String,
    val createdAt: String,
    val updatedAt: String,
    val dueDate: String
) {
    val createdAtInstant: Instant
        get() = Instant.parse(createdAt)
}

Custom Date Formats

For non-ISO formats like "06/15/2024":

object CustomDateSerializer : KSerializer<LocalDate> {
    private val formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy")
    override val descriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING)
    override fun serialize(encoder: Encoder, value: LocalDate) =
        encoder.encodeString(value.format(formatter))
    override fun deserialize(decoder: Decoder): LocalDate =
        LocalDate.parse(decoder.decodeString(), formatter)
}

Platform Decision Guide

Platform Recommended Library
Android (API 26+) java.time or kotlinx-datetime
Android (below API 26) kotlinx-datetime or ThreeTenABP
Kotlin Multiplatform kotlinx-datetime
JVM server java.time

Use Case

Virtually every API includes timestamps for created, updated, and expiry fields. Proper date handling in Kotlin ensures timezone-aware comparisons, correct display formatting across locales, and reliable duration calculations in scheduling apps.

Try It — JSON to Kotlin

Open full tool