From 892ff3b865c16d4162ec75e6f2bf9a7ac0ede262 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Tue, 23 Jul 2024 15:32:31 +0200 Subject: [PATCH 1/7] Provide custom serializers based on DateTimeFormat The names of the serializers are still under discussion, but it's already decided that the serializers are going to be abstract classes. Fixes #350 --- .../src/serializers/InstantSerializers.kt | 38 +++++++++++++++++++ .../src/serializers/LocalDateSerializers.kt | 31 +++++++++++++++ .../serializers/LocalDateTimeSerializers.kt | 23 +++++++++++ .../src/serializers/LocalTimeSerializers.kt | 21 ++++++++++ .../src/serializers/TimeZoneSerializers.kt | 23 +++++++++-- .../common/test/InstantSerializationTest.kt | 22 +++++++++++ .../common/test/LocalDateSerializationTest.kt | 13 +++++++ .../test/LocalDateTimeSerializationTest.kt | 21 ++++++++++ .../common/test/LocalTimeSerializationTest.kt | 20 ++++++++++ .../common/test/UtcOffsetSerializationTest.kt | 16 ++++++++ 10 files changed, 225 insertions(+), 3 deletions(-) diff --git a/core/common/src/serializers/InstantSerializers.kt b/core/common/src/serializers/InstantSerializers.kt index c64bdf475..01c213738 100644 --- a/core/common/src/serializers/InstantSerializers.kt +++ b/core/common/src/serializers/InstantSerializers.kt @@ -6,6 +6,9 @@ package kotlinx.datetime.serializers import kotlinx.datetime.Instant +import kotlinx.datetime.format +import kotlinx.datetime.format.DateTimeComponents +import kotlinx.datetime.format.DateTimeFormat import kotlinx.serialization.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* @@ -75,3 +78,38 @@ public object InstantComponentSerializer : KSerializer { } } + +/** + * An abstract serializer for [Instant] values that uses + * a custom [DateTimeFormat] for serializing to and deserializing. + * + * [format] should be a format that includes enough components to unambiguously define a date, a time, and a UTC offset. + * See [Instant.parse] for details of how deserialization is performed. + * + * When serializing, the [Instant] value is formatted as a string using the specified [format] + * in the [ZERO][UtcOffset.ZERO] UTC offset. + * + * This serializer is abstract and must be subclassed to provide a concrete serializer. + * Example: + * ``` + * object Rfc1123InstantSerializer : CustomInstantSerializer(DateTimeComponents.Formats.RFC_1123) + * ``` + * + * Note that [Instant] is [kotlinx.serialization.Serializable] by default, + * so it is not necessary to create custom serializers when the format is not important. + * Additionally, [InstantIso8601Serializer] is provided for the ISO 8601 format. + */ +public abstract class CustomInstantSerializer( + private val format: DateTimeFormat, +) : KSerializer { + + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("kotlinx.datetime.Instant", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): Instant = + Instant.parse(decoder.decodeString(), format) + + override fun serialize(encoder: Encoder, value: Instant) { + encoder.encodeString(value.format(format)) + } +} diff --git a/core/common/src/serializers/LocalDateSerializers.kt b/core/common/src/serializers/LocalDateSerializers.kt index 824ce518d..496321fe6 100644 --- a/core/common/src/serializers/LocalDateSerializers.kt +++ b/core/common/src/serializers/LocalDateSerializers.kt @@ -6,6 +6,7 @@ package kotlinx.datetime.serializers import kotlinx.datetime.* +import kotlinx.datetime.format.DateTimeFormat import kotlinx.serialization.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* @@ -76,3 +77,33 @@ public object LocalDateComponentSerializer: KSerializer { } } + +/** + * An abstract serializer for [LocalDate] values that uses + * a custom [DateTimeFormat] to serialize and deserialize the value. + * + * This serializer is abstract and must be subclassed to provide a concrete serializer. + * Example: + * ``` + * object IsoBasicLocalDateSerializer : CustomLocalDateSerializer(LocalDate.Formats.ISO_BASIC) + * ``` + * + * Note that [LocalDate] is [kotlinx.serialization.Serializable] by default, + * so it is not necessary to create custom serializers when the format is not important. + * Additionally, [LocalDateIso8601Serializer] is provided for the ISO 8601 format. + */ +public abstract class CustomLocalDateSerializer( + format: DateTimeFormat, +) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalDate") + +internal fun DateTimeFormat.asKSerializer(classFqn: String): KSerializer = + object : KSerializer { + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor(classFqn, PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): T = parse(decoder.decodeString()) + + override fun serialize(encoder: Encoder, value: T) { + encoder.encodeString(format(value)) + } + } diff --git a/core/common/src/serializers/LocalDateTimeSerializers.kt b/core/common/src/serializers/LocalDateTimeSerializers.kt index f9a455531..7caf27742 100644 --- a/core/common/src/serializers/LocalDateTimeSerializers.kt +++ b/core/common/src/serializers/LocalDateTimeSerializers.kt @@ -6,6 +6,7 @@ package kotlinx.datetime.serializers import kotlinx.datetime.* +import kotlinx.datetime.format.DateTimeFormat import kotlinx.serialization.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* @@ -98,3 +99,25 @@ public object LocalDateTimeComponentSerializer: KSerializer { } } + +/** + * An abstract serializer for [LocalDateTime] values that uses + * a custom [DateTimeFormat] to serialize and deserialize the value. + * + * This serializer is abstract and must be subclassed to provide a concrete serializer. + * Example: + * ``` + * object PythonDateTimeSerializer : CustomLocalDateTimeSerializer(LocalDateTime.Format { + * date(LocalDate.Formats.ISO) + * char(' ') + * time(LocalTime.Formats.ISO) + * }) + * ``` + * + * Note that [LocalDateTime] is [kotlinx.serialization.Serializable] by default, + * so it is not necessary to create custom serializers when the format is not important. + * Additionally, [LocalDateTimeIso8601Serializer] is provided for the ISO 8601 format. + */ +public abstract class CustomLocalDateTimeSerializer( + format: DateTimeFormat, +) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalDateTime") diff --git a/core/common/src/serializers/LocalTimeSerializers.kt b/core/common/src/serializers/LocalTimeSerializers.kt index b8c1c0ebd..90e034e7d 100644 --- a/core/common/src/serializers/LocalTimeSerializers.kt +++ b/core/common/src/serializers/LocalTimeSerializers.kt @@ -6,6 +6,7 @@ package kotlinx.datetime.serializers import kotlinx.datetime.* +import kotlinx.datetime.format.DateTimeFormat import kotlinx.serialization.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* @@ -81,3 +82,23 @@ public object LocalTimeComponentSerializer : KSerializer { } } } + +/** + * An abstract serializer for [LocalTime] values that uses + * a custom [DateTimeFormat] to serialize and deserialize the value. + * + * This serializer is abstract and must be subclassed to provide a concrete serializer. + * Example: + * ``` + * object FixedWidthTimeSerializer : CustomLocalTimeSerializer(LocalTime.Format { + * hour(); char(':'); minute(); char(':'); second(); char('.'); secondFraction(3) + * }) + * ``` + * + * Note that [LocalTime] is [kotlinx.serialization.Serializable] by default, + * so it is not necessary to create custom serializers when the format is not important. + * Additionally, [LocalTimeIso8601Serializer] is provided for the ISO 8601 format. + */ +public abstract class CustomLocalTimeSerializer( + format: DateTimeFormat, +) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalTime") diff --git a/core/common/src/serializers/TimeZoneSerializers.kt b/core/common/src/serializers/TimeZoneSerializers.kt index 2d6d1c38a..add5cc82d 100644 --- a/core/common/src/serializers/TimeZoneSerializers.kt +++ b/core/common/src/serializers/TimeZoneSerializers.kt @@ -5,9 +5,8 @@ package kotlinx.datetime.serializers -import kotlinx.datetime.FixedOffsetTimeZone -import kotlinx.datetime.TimeZone -import kotlinx.datetime.UtcOffset +import kotlinx.datetime.* +import kotlinx.datetime.format.DateTimeFormat import kotlinx.serialization.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* @@ -74,3 +73,21 @@ public object UtcOffsetSerializer: KSerializer { } } + +/** + * An abstract serializer for [UtcOffset] values that uses + * a custom [DateTimeFormat] to serialize and deserialize the value. + * + * This serializer is abstract and must be subclassed to provide a concrete serializer. + * Example: + * ``` + * object FourDigitOffsetSerializer : CustomUtcOffsetSerializer(UtcOffset.Formats.FOUR_DIGITS) + * ``` + * + * Note that [UtcOffset] is [kotlinx.serialization.Serializable] by default, + * so it is not necessary to create custom serializers when the format is not important. + * Additionally, [UtcOffsetSerializer] is provided for the ISO 8601 format. + */ +public abstract class CustomUtcOffsetSerializer( + format: DateTimeFormat, +) : KSerializer by format.asKSerializer("kotlinx.datetime.UtcOffset") diff --git a/serialization/common/test/InstantSerializationTest.kt b/serialization/common/test/InstantSerializationTest.kt index dea5c2dbd..564f609d3 100644 --- a/serialization/common/test/InstantSerializationTest.kt +++ b/serialization/common/test/InstantSerializationTest.kt @@ -5,6 +5,7 @@ package kotlinx.datetime.serialization.test import kotlinx.datetime.* +import kotlinx.datetime.format.DateTimeComponents import kotlinx.datetime.serializers.* import kotlinx.serialization.* import kotlinx.serialization.json.* @@ -66,4 +67,25 @@ class InstantSerializationTest { // should be the same as the ISO 8601 iso8601Serialization(Json.serializersModule.serializer()) } + + object Rfc1123InstantSerializer : CustomInstantSerializer(DateTimeComponents.Formats.RFC_1123) + + @Test + fun testCustomSerializer() { + for ((instant, json) in listOf( + Pair(Instant.fromEpochSeconds(1607505416), + "\"Wed, 9 Dec 2020 09:16:56 GMT\""), + Pair(Instant.fromEpochSeconds(-1607505416), + "\"Thu, 23 Jan 1919 14:43:04 GMT\""), + Pair(Instant.fromEpochSeconds(987654321), + "\"Thu, 19 Apr 2001 04:25:21 GMT\""), + )) { + assertEquals(json, Json.encodeToString(Rfc1123InstantSerializer, instant)) + assertEquals(instant, Json.decodeFromString(Rfc1123InstantSerializer, json)) + } + assertEquals("\"Thu, 19 Apr 2001 04:25:21 GMT\"", + Json.encodeToString(Rfc1123InstantSerializer, Instant.fromEpochSeconds(987654321, 123456789))) + assertEquals(Instant.fromEpochSeconds(987654321), + Json.decodeFromString(Rfc1123InstantSerializer, "\"Thu, 19 Apr 2001 08:25:21 +0400\"")) + } } diff --git a/serialization/common/test/LocalDateSerializationTest.kt b/serialization/common/test/LocalDateSerializationTest.kt index 91ed38277..d4e547cf4 100644 --- a/serialization/common/test/LocalDateSerializationTest.kt +++ b/serialization/common/test/LocalDateSerializationTest.kt @@ -70,4 +70,17 @@ class LocalDateSerializationTest { iso8601Serialization(Json.serializersModule.serializer()) } + object IsoBasicLocalDateSerializer : CustomLocalDateSerializer(LocalDate.Formats.ISO_BASIC) + + @Test + fun testCustomSerializer() { + for ((localDate, json) in listOf( + Pair(LocalDate(2020, 12, 9), "\"20201209\""), + Pair(LocalDate(-2020, 1, 1), "\"-20200101\""), + Pair(LocalDate(2019, 10, 1), "\"20191001\""), + )) { + assertEquals(json, Json.encodeToString(IsoBasicLocalDateSerializer, localDate)) + assertEquals(localDate, Json.decodeFromString(IsoBasicLocalDateSerializer, json)) + } + } } diff --git a/serialization/common/test/LocalDateTimeSerializationTest.kt b/serialization/common/test/LocalDateTimeSerializationTest.kt index c01e647c0..7f6030b22 100644 --- a/serialization/common/test/LocalDateTimeSerializationTest.kt +++ b/serialization/common/test/LocalDateTimeSerializationTest.kt @@ -6,6 +6,7 @@ package kotlinx.datetime.serialization.test import kotlinx.datetime.* +import kotlinx.datetime.format.char import kotlinx.datetime.serializers.* import kotlinx.serialization.KSerializer import kotlinx.serialization.json.* @@ -82,4 +83,24 @@ class LocalDateTimeSerializationTest { // should be the same as the ISO 8601 iso8601Serialization(Json.serializersModule.serializer()) } + + object PythonDateTimeSerializer : CustomLocalDateTimeSerializer(LocalDateTime.Format { + date(LocalDate.Formats.ISO) + char(' ') + time(LocalTime.Formats.ISO) + }) + + @Test + fun testCustomSerializer() { + for ((localDateTime, json) in listOf( + Pair(LocalDateTime(2008, 7, 5, 2, 1), "\"2008-07-05 02:01:00\""), + Pair(LocalDateTime(2007, 12, 31, 23, 59, 1), "\"2007-12-31 23:59:01\""), + Pair(LocalDateTime(999, 12, 31, 23, 59, 59, 990000000), "\"0999-12-31 23:59:59.99\""), + Pair(LocalDateTime(-1, 1, 2, 23, 59, 59, 999990000), "\"-0001-01-02 23:59:59.99999\""), + Pair(LocalDateTime(-2008, 1, 2, 23, 59, 59, 999999990), "\"-2008-01-02 23:59:59.99999999\""), + )) { + assertEquals(json, Json.encodeToString(PythonDateTimeSerializer, localDateTime)) + assertEquals(localDateTime, Json.decodeFromString(PythonDateTimeSerializer, json)) + } + } } diff --git a/serialization/common/test/LocalTimeSerializationTest.kt b/serialization/common/test/LocalTimeSerializationTest.kt index 5df81f542..4e4d3847e 100644 --- a/serialization/common/test/LocalTimeSerializationTest.kt +++ b/serialization/common/test/LocalTimeSerializationTest.kt @@ -6,6 +6,7 @@ package kotlinx.datetime.serialization.test import kotlinx.datetime.* +import kotlinx.datetime.format.char import kotlinx.datetime.serializers.* import kotlinx.serialization.KSerializer import kotlinx.serialization.json.* @@ -72,4 +73,23 @@ class LocalTimeSerializationTest { // should be the same as the ISO 8601 iso8601Serialization(Json.serializersModule.serializer()) } + + object FixedWidthTimeSerializer : CustomLocalTimeSerializer(LocalTime.Format { + hour(); char(':'); minute(); char(':'); second(); char('.'); secondFraction(3) + }) + + @Test + fun testCustomSerializer() { + for ((localTime, json) in listOf( + Pair(LocalTime(2, 1), "\"02:01:00.000\""), + Pair(LocalTime(23, 59, 1), "\"23:59:01.000\""), + Pair(LocalTime(23, 59, 59, 990000000), "\"23:59:59.990\""), + Pair(LocalTime(23, 59, 59, 999000000), "\"23:59:59.999\""), + )) { + assertEquals(json, Json.encodeToString(FixedWidthTimeSerializer, localTime)) + assertEquals(localTime, Json.decodeFromString(FixedWidthTimeSerializer, json)) + } + assertEquals("\"12:34:56.123\"", Json.encodeToString(FixedWidthTimeSerializer, + LocalTime(12, 34, 56, 123999999))) + } } diff --git a/serialization/common/test/UtcOffsetSerializationTest.kt b/serialization/common/test/UtcOffsetSerializationTest.kt index 2504d6fb6..a1b053cbd 100644 --- a/serialization/common/test/UtcOffsetSerializationTest.kt +++ b/serialization/common/test/UtcOffsetSerializationTest.kt @@ -35,4 +35,20 @@ class UtcOffsetSerializationTest { testSerializationAsPrimitive(UtcOffsetSerializer) testSerializationAsPrimitive(UtcOffset.serializer()) } + + object FourDigitOffsetSerializer : CustomUtcOffsetSerializer(UtcOffset.Formats.FOUR_DIGITS) + + @Test + fun testCustomSerializer() { + for ((utcOffset, json) in listOf( + Pair(UtcOffset.ZERO, "\"+0000\""), + Pair(UtcOffset(2), "\"+0200\""), + Pair(UtcOffset(2, 30), "\"+0230\""), + Pair(UtcOffset(-2, -30), "\"-0230\""), + )) { + assertEquals(json, Json.encodeToString(FourDigitOffsetSerializer, utcOffset)) + assertEquals(utcOffset, Json.decodeFromString(FourDigitOffsetSerializer, json)) + } + assertEquals("\"+1234\"", Json.encodeToString(FourDigitOffsetSerializer, UtcOffset(12, 34, 56))) + } } From aaf0a8b358cd4de99f3d6f3393f6ae4c277d47d2 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Thu, 25 Jul 2024 11:20:22 +0200 Subject: [PATCH 2/7] Rename the abstract serializers --- core/common/src/serializers/InstantSerializers.kt | 4 ++-- core/common/src/serializers/LocalDateSerializers.kt | 4 ++-- core/common/src/serializers/LocalDateTimeSerializers.kt | 4 ++-- core/common/src/serializers/LocalTimeSerializers.kt | 4 ++-- core/common/src/serializers/TimeZoneSerializers.kt | 4 ++-- serialization/common/test/InstantSerializationTest.kt | 2 +- serialization/common/test/LocalDateSerializationTest.kt | 2 +- serialization/common/test/LocalDateTimeSerializationTest.kt | 2 +- serialization/common/test/LocalTimeSerializationTest.kt | 2 +- serialization/common/test/UtcOffsetSerializationTest.kt | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/common/src/serializers/InstantSerializers.kt b/core/common/src/serializers/InstantSerializers.kt index 01c213738..284df66c9 100644 --- a/core/common/src/serializers/InstantSerializers.kt +++ b/core/common/src/serializers/InstantSerializers.kt @@ -92,14 +92,14 @@ public object InstantComponentSerializer : KSerializer { * This serializer is abstract and must be subclassed to provide a concrete serializer. * Example: * ``` - * object Rfc1123InstantSerializer : CustomInstantSerializer(DateTimeComponents.Formats.RFC_1123) + * object Rfc1123InstantSerializer : FormattedInstantSerializer(DateTimeComponents.Formats.RFC_1123) * ``` * * Note that [Instant] is [kotlinx.serialization.Serializable] by default, * so it is not necessary to create custom serializers when the format is not important. * Additionally, [InstantIso8601Serializer] is provided for the ISO 8601 format. */ -public abstract class CustomInstantSerializer( +public abstract class FormattedInstantSerializer( private val format: DateTimeFormat, ) : KSerializer { diff --git a/core/common/src/serializers/LocalDateSerializers.kt b/core/common/src/serializers/LocalDateSerializers.kt index 496321fe6..e04486018 100644 --- a/core/common/src/serializers/LocalDateSerializers.kt +++ b/core/common/src/serializers/LocalDateSerializers.kt @@ -85,14 +85,14 @@ public object LocalDateComponentSerializer: KSerializer { * This serializer is abstract and must be subclassed to provide a concrete serializer. * Example: * ``` - * object IsoBasicLocalDateSerializer : CustomLocalDateSerializer(LocalDate.Formats.ISO_BASIC) + * object IsoBasicLocalDateSerializer : FormattedLocalDateSerializer(LocalDate.Formats.ISO_BASIC) * ``` * * Note that [LocalDate] is [kotlinx.serialization.Serializable] by default, * so it is not necessary to create custom serializers when the format is not important. * Additionally, [LocalDateIso8601Serializer] is provided for the ISO 8601 format. */ -public abstract class CustomLocalDateSerializer( +public abstract class FormattedLocalDateSerializer( format: DateTimeFormat, ) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalDate") diff --git a/core/common/src/serializers/LocalDateTimeSerializers.kt b/core/common/src/serializers/LocalDateTimeSerializers.kt index 7caf27742..9b0a63e7e 100644 --- a/core/common/src/serializers/LocalDateTimeSerializers.kt +++ b/core/common/src/serializers/LocalDateTimeSerializers.kt @@ -107,7 +107,7 @@ public object LocalDateTimeComponentSerializer: KSerializer { * This serializer is abstract and must be subclassed to provide a concrete serializer. * Example: * ``` - * object PythonDateTimeSerializer : CustomLocalDateTimeSerializer(LocalDateTime.Format { + * object PythonDateTimeSerializer : FormattedLocalDateTimeSerializer(LocalDateTime.Format { * date(LocalDate.Formats.ISO) * char(' ') * time(LocalTime.Formats.ISO) @@ -118,6 +118,6 @@ public object LocalDateTimeComponentSerializer: KSerializer { * so it is not necessary to create custom serializers when the format is not important. * Additionally, [LocalDateTimeIso8601Serializer] is provided for the ISO 8601 format. */ -public abstract class CustomLocalDateTimeSerializer( +public abstract class FormattedLocalDateTimeSerializer( format: DateTimeFormat, ) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalDateTime") diff --git a/core/common/src/serializers/LocalTimeSerializers.kt b/core/common/src/serializers/LocalTimeSerializers.kt index 90e034e7d..fc2ce85e2 100644 --- a/core/common/src/serializers/LocalTimeSerializers.kt +++ b/core/common/src/serializers/LocalTimeSerializers.kt @@ -90,7 +90,7 @@ public object LocalTimeComponentSerializer : KSerializer { * This serializer is abstract and must be subclassed to provide a concrete serializer. * Example: * ``` - * object FixedWidthTimeSerializer : CustomLocalTimeSerializer(LocalTime.Format { + * object FixedWidthTimeSerializer : FormattedLocalTimeSerializer(LocalTime.Format { * hour(); char(':'); minute(); char(':'); second(); char('.'); secondFraction(3) * }) * ``` @@ -99,6 +99,6 @@ public object LocalTimeComponentSerializer : KSerializer { * so it is not necessary to create custom serializers when the format is not important. * Additionally, [LocalTimeIso8601Serializer] is provided for the ISO 8601 format. */ -public abstract class CustomLocalTimeSerializer( +public abstract class FormattedLocalTimeSerializer( format: DateTimeFormat, ) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalTime") diff --git a/core/common/src/serializers/TimeZoneSerializers.kt b/core/common/src/serializers/TimeZoneSerializers.kt index add5cc82d..3c2cc9333 100644 --- a/core/common/src/serializers/TimeZoneSerializers.kt +++ b/core/common/src/serializers/TimeZoneSerializers.kt @@ -81,13 +81,13 @@ public object UtcOffsetSerializer: KSerializer { * This serializer is abstract and must be subclassed to provide a concrete serializer. * Example: * ``` - * object FourDigitOffsetSerializer : CustomUtcOffsetSerializer(UtcOffset.Formats.FOUR_DIGITS) + * object FourDigitOffsetSerializer : FormattedUtcOffsetSerializer(UtcOffset.Formats.FOUR_DIGITS) * ``` * * Note that [UtcOffset] is [kotlinx.serialization.Serializable] by default, * so it is not necessary to create custom serializers when the format is not important. * Additionally, [UtcOffsetSerializer] is provided for the ISO 8601 format. */ -public abstract class CustomUtcOffsetSerializer( +public abstract class FormattedUtcOffsetSerializer( format: DateTimeFormat, ) : KSerializer by format.asKSerializer("kotlinx.datetime.UtcOffset") diff --git a/serialization/common/test/InstantSerializationTest.kt b/serialization/common/test/InstantSerializationTest.kt index 564f609d3..237c735cc 100644 --- a/serialization/common/test/InstantSerializationTest.kt +++ b/serialization/common/test/InstantSerializationTest.kt @@ -68,7 +68,7 @@ class InstantSerializationTest { iso8601Serialization(Json.serializersModule.serializer()) } - object Rfc1123InstantSerializer : CustomInstantSerializer(DateTimeComponents.Formats.RFC_1123) + object Rfc1123InstantSerializer : FormattedInstantSerializer(DateTimeComponents.Formats.RFC_1123) @Test fun testCustomSerializer() { diff --git a/serialization/common/test/LocalDateSerializationTest.kt b/serialization/common/test/LocalDateSerializationTest.kt index d4e547cf4..086d01107 100644 --- a/serialization/common/test/LocalDateSerializationTest.kt +++ b/serialization/common/test/LocalDateSerializationTest.kt @@ -70,7 +70,7 @@ class LocalDateSerializationTest { iso8601Serialization(Json.serializersModule.serializer()) } - object IsoBasicLocalDateSerializer : CustomLocalDateSerializer(LocalDate.Formats.ISO_BASIC) + object IsoBasicLocalDateSerializer : FormattedLocalDateSerializer(LocalDate.Formats.ISO_BASIC) @Test fun testCustomSerializer() { diff --git a/serialization/common/test/LocalDateTimeSerializationTest.kt b/serialization/common/test/LocalDateTimeSerializationTest.kt index 7f6030b22..bab9200c5 100644 --- a/serialization/common/test/LocalDateTimeSerializationTest.kt +++ b/serialization/common/test/LocalDateTimeSerializationTest.kt @@ -84,7 +84,7 @@ class LocalDateTimeSerializationTest { iso8601Serialization(Json.serializersModule.serializer()) } - object PythonDateTimeSerializer : CustomLocalDateTimeSerializer(LocalDateTime.Format { + object PythonDateTimeSerializer : FormattedLocalDateTimeSerializer(LocalDateTime.Format { date(LocalDate.Formats.ISO) char(' ') time(LocalTime.Formats.ISO) diff --git a/serialization/common/test/LocalTimeSerializationTest.kt b/serialization/common/test/LocalTimeSerializationTest.kt index 4e4d3847e..058bba6f4 100644 --- a/serialization/common/test/LocalTimeSerializationTest.kt +++ b/serialization/common/test/LocalTimeSerializationTest.kt @@ -74,7 +74,7 @@ class LocalTimeSerializationTest { iso8601Serialization(Json.serializersModule.serializer()) } - object FixedWidthTimeSerializer : CustomLocalTimeSerializer(LocalTime.Format { + object FixedWidthTimeSerializer : FormattedLocalTimeSerializer(LocalTime.Format { hour(); char(':'); minute(); char(':'); second(); char('.'); secondFraction(3) }) diff --git a/serialization/common/test/UtcOffsetSerializationTest.kt b/serialization/common/test/UtcOffsetSerializationTest.kt index a1b053cbd..6885f3fdf 100644 --- a/serialization/common/test/UtcOffsetSerializationTest.kt +++ b/serialization/common/test/UtcOffsetSerializationTest.kt @@ -36,7 +36,7 @@ class UtcOffsetSerializationTest { testSerializationAsPrimitive(UtcOffset.serializer()) } - object FourDigitOffsetSerializer : CustomUtcOffsetSerializer(UtcOffset.Formats.FOUR_DIGITS) + object FourDigitOffsetSerializer : FormattedUtcOffsetSerializer(UtcOffset.Formats.FOUR_DIGITS) @Test fun testCustomSerializer() { From f2a7376253ff5d173b211ce19e4cd6ab6682380f Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Thu, 25 Jul 2024 14:22:17 +0200 Subject: [PATCH 3/7] Add the `name` parameter to custom serializers --- .../src/serializers/InstantSerializers.kt | 22 ++++++++++++++---- .../src/serializers/LocalDateSerializers.kt | 20 ++++++++++++---- .../serializers/LocalDateTimeSerializers.kt | 23 +++++++++++++------ .../src/serializers/LocalTimeSerializers.kt | 13 ++++++++--- .../src/serializers/TimeZoneSerializers.kt | 15 +++++++++--- .../common/test/InstantSerializationTest.kt | 3 ++- .../common/test/LocalDateSerializationTest.kt | 8 ++++++- .../test/LocalDateTimeSerializationTest.kt | 3 ++- .../common/test/LocalTimeSerializationTest.kt | 3 ++- .../common/test/UtcOffsetSerializationTest.kt | 3 ++- 10 files changed, 85 insertions(+), 28 deletions(-) diff --git a/core/common/src/serializers/InstantSerializers.kt b/core/common/src/serializers/InstantSerializers.kt index 284df66c9..3e5db5a9a 100644 --- a/core/common/src/serializers/InstantSerializers.kt +++ b/core/common/src/serializers/InstantSerializers.kt @@ -5,8 +5,7 @@ package kotlinx.datetime.serializers -import kotlinx.datetime.Instant -import kotlinx.datetime.format +import kotlinx.datetime.* import kotlinx.datetime.format.DateTimeComponents import kotlinx.datetime.format.DateTimeFormat import kotlinx.serialization.* @@ -86,13 +85,23 @@ public object InstantComponentSerializer : KSerializer { * [format] should be a format that includes enough components to unambiguously define a date, a time, and a UTC offset. * See [Instant.parse] for details of how deserialization is performed. * + * [name] is the name of the serializer. + * The [SerialDescriptor.serialName] of the resulting serializer is `kotlinx.datetime.Instant serializer `[name]. + * [SerialDescriptor.serialName] must be unique across all serializers in the same serialization context. + * When defining a serializer in a library, it is recommended to use the fully qualified class name in [name] + * to avoid conflicts with serializers defined by other libraries and client code. + * * When serializing, the [Instant] value is formatted as a string using the specified [format] * in the [ZERO][UtcOffset.ZERO] UTC offset. * * This serializer is abstract and must be subclassed to provide a concrete serializer. * Example: * ``` - * object Rfc1123InstantSerializer : FormattedInstantSerializer(DateTimeComponents.Formats.RFC_1123) + * // serializes LocalDateTime(2008, 6, 30, 11, 5, 30).toInstant(TimeZone.UTC) + * // as the string "Mon, 30 Jun 2008 11:05:30 GMT" + * object Rfc1123InstantSerializer : FormattedInstantSerializer( + * "my.package.RFC1123", DateTimeComponents.Formats.RFC_1123 + * ) * ``` * * Note that [Instant] is [kotlinx.serialization.Serializable] by default, @@ -100,11 +109,11 @@ public object InstantComponentSerializer : KSerializer { * Additionally, [InstantIso8601Serializer] is provided for the ISO 8601 format. */ public abstract class FormattedInstantSerializer( + name: String, private val format: DateTimeFormat, ) : KSerializer { - override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("kotlinx.datetime.Instant", PrimitiveKind.STRING) + PrimitiveSerialDescriptor("kotlinx.datetime.Instant serializer $name", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): Instant = Instant.parse(decoder.decodeString(), format) @@ -112,4 +121,7 @@ public abstract class FormattedInstantSerializer( override fun serialize(encoder: Encoder, value: Instant) { encoder.encodeString(value.format(format)) } + + @OptIn(ExperimentalSerializationApi::class) + override fun toString(): String = descriptor.serialName } diff --git a/core/common/src/serializers/LocalDateSerializers.kt b/core/common/src/serializers/LocalDateSerializers.kt index e04486018..6618246eb 100644 --- a/core/common/src/serializers/LocalDateSerializers.kt +++ b/core/common/src/serializers/LocalDateSerializers.kt @@ -82,10 +82,18 @@ public object LocalDateComponentSerializer: KSerializer { * An abstract serializer for [LocalDate] values that uses * a custom [DateTimeFormat] to serialize and deserialize the value. * + * [name] is the name of the serializer. + * The [SerialDescriptor.serialName] of the resulting serializer is `kotlinx.datetime.LocalDate serializer `[name]. + * [SerialDescriptor.serialName] must be unique across all serializers in the same serialization context. + * When defining a serializer in a library, it is recommended to use the fully qualified class name in [name] + * to avoid conflicts with serializers defined by other libraries and client code. + * * This serializer is abstract and must be subclassed to provide a concrete serializer. * Example: * ``` - * object IsoBasicLocalDateSerializer : FormattedLocalDateSerializer(LocalDate.Formats.ISO_BASIC) + * // serializes LocalDate(2020, 1, 4) as the string "20200104" + * object IsoBasicLocalDateSerializer : + * FormattedLocalDateSerializer("my.package.ISO_BASIC", LocalDate.Formats.ISO_BASIC) * ``` * * Note that [LocalDate] is [kotlinx.serialization.Serializable] by default, @@ -93,17 +101,19 @@ public object LocalDateComponentSerializer: KSerializer { * Additionally, [LocalDateIso8601Serializer] is provided for the ISO 8601 format. */ public abstract class FormattedLocalDateSerializer( - format: DateTimeFormat, -) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalDate") + name: String, format: DateTimeFormat +) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalDate serializer $name") -internal fun DateTimeFormat.asKSerializer(classFqn: String): KSerializer = +internal fun DateTimeFormat.asKSerializer(serialName: String): KSerializer = object : KSerializer { override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor(classFqn, PrimitiveKind.STRING) + PrimitiveSerialDescriptor(serialName, PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): T = parse(decoder.decodeString()) override fun serialize(encoder: Encoder, value: T) { encoder.encodeString(format(value)) } + + override fun toString(): String = serialName } diff --git a/core/common/src/serializers/LocalDateTimeSerializers.kt b/core/common/src/serializers/LocalDateTimeSerializers.kt index 9b0a63e7e..4b6a86536 100644 --- a/core/common/src/serializers/LocalDateTimeSerializers.kt +++ b/core/common/src/serializers/LocalDateTimeSerializers.kt @@ -104,14 +104,23 @@ public object LocalDateTimeComponentSerializer: KSerializer { * An abstract serializer for [LocalDateTime] values that uses * a custom [DateTimeFormat] to serialize and deserialize the value. * + * [name] is the name of the serializer. + * The [SerialDescriptor.serialName] of the resulting serializer is `kotlinx.datetime.LocalDateTime serializer `[name]. + * [SerialDescriptor.serialName] must be unique across all serializers in the same serialization context. + * When defining a serializer in a library, it is recommended to use the fully qualified class name in [name] + * to avoid conflicts with serializers defined by other libraries and client code. + * * This serializer is abstract and must be subclassed to provide a concrete serializer. * Example: * ``` - * object PythonDateTimeSerializer : FormattedLocalDateTimeSerializer(LocalDateTime.Format { - * date(LocalDate.Formats.ISO) - * char(' ') - * time(LocalTime.Formats.ISO) - * }) + * // serializes LocalDateTime(2020, 1, 4, 12, 30) as the string "2020-01-04 12:30" + * object PythonDateTimeSerializer : FormattedLocalDateTimeSerializer("my.package.PythonDateTime", + * LocalDateTime.Format { + * date(LocalDate.Formats.ISO) + * char(' ') + * time(LocalTime.Formats.ISO) + * } + * ) * ``` * * Note that [LocalDateTime] is [kotlinx.serialization.Serializable] by default, @@ -119,5 +128,5 @@ public object LocalDateTimeComponentSerializer: KSerializer { * Additionally, [LocalDateTimeIso8601Serializer] is provided for the ISO 8601 format. */ public abstract class FormattedLocalDateTimeSerializer( - format: DateTimeFormat, -) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalDateTime") + name: String, format: DateTimeFormat +) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalDateTime serializer $name") diff --git a/core/common/src/serializers/LocalTimeSerializers.kt b/core/common/src/serializers/LocalTimeSerializers.kt index fc2ce85e2..10a3750e2 100644 --- a/core/common/src/serializers/LocalTimeSerializers.kt +++ b/core/common/src/serializers/LocalTimeSerializers.kt @@ -87,10 +87,17 @@ public object LocalTimeComponentSerializer : KSerializer { * An abstract serializer for [LocalTime] values that uses * a custom [DateTimeFormat] to serialize and deserialize the value. * + * [name] is the name of the serializer. + * The [SerialDescriptor.serialName] of the resulting serializer is `kotlinx.datetime.LocalTime serializer `[name]. + * [SerialDescriptor.serialName] must be unique across all serializers in the same serialization context. + * When defining a serializer in a library, it is recommended to use the fully qualified class name in [name] + * to avoid conflicts with serializers defined by other libraries and client code. + * * This serializer is abstract and must be subclassed to provide a concrete serializer. * Example: * ``` - * object FixedWidthTimeSerializer : FormattedLocalTimeSerializer(LocalTime.Format { + * // serializes LocalTime(12, 30) as "12:30:00.000" + * object FixedWidthTimeSerializer : FormattedLocalTimeSerializer("my.package.FixedWidthTime", LocalTime.Format { * hour(); char(':'); minute(); char(':'); second(); char('.'); secondFraction(3) * }) * ``` @@ -100,5 +107,5 @@ public object LocalTimeComponentSerializer : KSerializer { * Additionally, [LocalTimeIso8601Serializer] is provided for the ISO 8601 format. */ public abstract class FormattedLocalTimeSerializer( - format: DateTimeFormat, -) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalTime") + name: String, format: DateTimeFormat +) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalTime serializer $name") diff --git a/core/common/src/serializers/TimeZoneSerializers.kt b/core/common/src/serializers/TimeZoneSerializers.kt index 3c2cc9333..b0d5c5071 100644 --- a/core/common/src/serializers/TimeZoneSerializers.kt +++ b/core/common/src/serializers/TimeZoneSerializers.kt @@ -78,10 +78,19 @@ public object UtcOffsetSerializer: KSerializer { * An abstract serializer for [UtcOffset] values that uses * a custom [DateTimeFormat] to serialize and deserialize the value. * + * [name] is the name of the serializer. + * The [SerialDescriptor.serialName] of the resulting serializer is `kotlinx.datetime.UtcOffset serializer `[name]. + * [SerialDescriptor.serialName] must be unique across all serializers in the same serialization context. + * When defining a serializer in a library, it is recommended to use the fully qualified class name in [name] + * to avoid conflicts with serializers defined by other libraries and client code. + * * This serializer is abstract and must be subclassed to provide a concrete serializer. * Example: * ``` - * object FourDigitOffsetSerializer : FormattedUtcOffsetSerializer(UtcOffset.Formats.FOUR_DIGITS) + * // serializes the UTC offset UtcOffset(hours = 2) as the string "+0200" + * object FourDigitOffsetSerializer : FormattedUtcOffsetSerializer( + * "my.package.FOUR_DIGITS", UtcOffset.Formats.FOUR_DIGITS + * ) * ``` * * Note that [UtcOffset] is [kotlinx.serialization.Serializable] by default, @@ -89,5 +98,5 @@ public object UtcOffsetSerializer: KSerializer { * Additionally, [UtcOffsetSerializer] is provided for the ISO 8601 format. */ public abstract class FormattedUtcOffsetSerializer( - format: DateTimeFormat, -) : KSerializer by format.asKSerializer("kotlinx.datetime.UtcOffset") + name: String, format: DateTimeFormat +) : KSerializer by format.asKSerializer("kotlinx.datetime.UtcOffset serializer $name") diff --git a/serialization/common/test/InstantSerializationTest.kt b/serialization/common/test/InstantSerializationTest.kt index 237c735cc..ed0919e27 100644 --- a/serialization/common/test/InstantSerializationTest.kt +++ b/serialization/common/test/InstantSerializationTest.kt @@ -68,10 +68,11 @@ class InstantSerializationTest { iso8601Serialization(Json.serializersModule.serializer()) } - object Rfc1123InstantSerializer : FormattedInstantSerializer(DateTimeComponents.Formats.RFC_1123) + object Rfc1123InstantSerializer : FormattedInstantSerializer("RFC_1123", DateTimeComponents.Formats.RFC_1123) @Test fun testCustomSerializer() { + assertKSerializerName("kotlinx.datetime.Instant serializer RFC_1123", Rfc1123InstantSerializer) for ((instant, json) in listOf( Pair(Instant.fromEpochSeconds(1607505416), "\"Wed, 9 Dec 2020 09:16:56 GMT\""), diff --git a/serialization/common/test/LocalDateSerializationTest.kt b/serialization/common/test/LocalDateSerializationTest.kt index 086d01107..c6ca20136 100644 --- a/serialization/common/test/LocalDateSerializationTest.kt +++ b/serialization/common/test/LocalDateSerializationTest.kt @@ -70,10 +70,11 @@ class LocalDateSerializationTest { iso8601Serialization(Json.serializersModule.serializer()) } - object IsoBasicLocalDateSerializer : FormattedLocalDateSerializer(LocalDate.Formats.ISO_BASIC) + object IsoBasicLocalDateSerializer : FormattedLocalDateSerializer("ISO_BASIC", LocalDate.Formats.ISO_BASIC) @Test fun testCustomSerializer() { + assertKSerializerName("kotlinx.datetime.LocalDate serializer ISO_BASIC", IsoBasicLocalDateSerializer) for ((localDate, json) in listOf( Pair(LocalDate(2020, 12, 9), "\"20201209\""), Pair(LocalDate(-2020, 1, 1), "\"-20200101\""), @@ -84,3 +85,8 @@ class LocalDateSerializationTest { } } } + +@OptIn(ExperimentalSerializationApi::class) +fun assertKSerializerName(expectedName: String, serializer: KSerializer) { + assertEquals(expectedName, serializer.descriptor.serialName) +} diff --git a/serialization/common/test/LocalDateTimeSerializationTest.kt b/serialization/common/test/LocalDateTimeSerializationTest.kt index bab9200c5..e780ed397 100644 --- a/serialization/common/test/LocalDateTimeSerializationTest.kt +++ b/serialization/common/test/LocalDateTimeSerializationTest.kt @@ -84,7 +84,7 @@ class LocalDateTimeSerializationTest { iso8601Serialization(Json.serializersModule.serializer()) } - object PythonDateTimeSerializer : FormattedLocalDateTimeSerializer(LocalDateTime.Format { + object PythonDateTimeSerializer : FormattedLocalDateTimeSerializer("PythonDateTime", LocalDateTime.Format { date(LocalDate.Formats.ISO) char(' ') time(LocalTime.Formats.ISO) @@ -92,6 +92,7 @@ class LocalDateTimeSerializationTest { @Test fun testCustomSerializer() { + assertKSerializerName("kotlinx.datetime.LocalDateTime serializer PythonDateTime", PythonDateTimeSerializer) for ((localDateTime, json) in listOf( Pair(LocalDateTime(2008, 7, 5, 2, 1), "\"2008-07-05 02:01:00\""), Pair(LocalDateTime(2007, 12, 31, 23, 59, 1), "\"2007-12-31 23:59:01\""), diff --git a/serialization/common/test/LocalTimeSerializationTest.kt b/serialization/common/test/LocalTimeSerializationTest.kt index 058bba6f4..9cf423998 100644 --- a/serialization/common/test/LocalTimeSerializationTest.kt +++ b/serialization/common/test/LocalTimeSerializationTest.kt @@ -74,12 +74,13 @@ class LocalTimeSerializationTest { iso8601Serialization(Json.serializersModule.serializer()) } - object FixedWidthTimeSerializer : FormattedLocalTimeSerializer(LocalTime.Format { + object FixedWidthTimeSerializer : FormattedLocalTimeSerializer("FixedWidth", LocalTime.Format { hour(); char(':'); minute(); char(':'); second(); char('.'); secondFraction(3) }) @Test fun testCustomSerializer() { + assertKSerializerName("kotlinx.datetime.LocalTime serializer FixedWidth", FixedWidthTimeSerializer) for ((localTime, json) in listOf( Pair(LocalTime(2, 1), "\"02:01:00.000\""), Pair(LocalTime(23, 59, 1), "\"23:59:01.000\""), diff --git a/serialization/common/test/UtcOffsetSerializationTest.kt b/serialization/common/test/UtcOffsetSerializationTest.kt index 6885f3fdf..5c2064e7a 100644 --- a/serialization/common/test/UtcOffsetSerializationTest.kt +++ b/serialization/common/test/UtcOffsetSerializationTest.kt @@ -36,10 +36,11 @@ class UtcOffsetSerializationTest { testSerializationAsPrimitive(UtcOffset.serializer()) } - object FourDigitOffsetSerializer : FormattedUtcOffsetSerializer(UtcOffset.Formats.FOUR_DIGITS) + object FourDigitOffsetSerializer : FormattedUtcOffsetSerializer("FOUR_DIGITS", UtcOffset.Formats.FOUR_DIGITS) @Test fun testCustomSerializer() { + assertKSerializerName("kotlinx.datetime.UtcOffset serializer FOUR_DIGITS", FourDigitOffsetSerializer) for ((utcOffset, json) in listOf( Pair(UtcOffset.ZERO, "\"+0000\""), Pair(UtcOffset(2), "\"+0200\""), From 5dea535ee156df2cb844cd7b867a35d7859ca7b4 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Thu, 25 Jul 2024 14:39:38 +0200 Subject: [PATCH 4/7] Document the existing serial descriptor names --- .../common/test/DateTimePeriodSerializationTest.kt | 6 ++++++ .../common/test/DateTimeUnitSerializationTest.kt | 8 ++++++-- serialization/common/test/DayOfWeekSerializationTest.kt | 3 ++- serialization/common/test/InstantSerializationTest.kt | 3 +++ serialization/common/test/LocalDateSerializationTest.kt | 3 +++ .../common/test/LocalDateTimeSerializationTest.kt | 3 +++ serialization/common/test/LocalTimeSerializationTest.kt | 3 +++ serialization/common/test/MonthSerializationTest.kt | 3 ++- serialization/common/test/TimeZoneSerializationTest.kt | 6 +++++- serialization/common/test/UtcOffsetSerializationTest.kt | 2 ++ 10 files changed, 35 insertions(+), 5 deletions(-) diff --git a/serialization/common/test/DateTimePeriodSerializationTest.kt b/serialization/common/test/DateTimePeriodSerializationTest.kt index a8cb1a6c5..ddb2f606d 100644 --- a/serialization/common/test/DateTimePeriodSerializationTest.kt +++ b/serialization/common/test/DateTimePeriodSerializationTest.kt @@ -97,28 +97,34 @@ class DateTimePeriodSerializationTest { @Test fun testDatePeriodIso8601Serialization() { + assertKSerializerName("kotlinx.datetime.DatePeriod", DatePeriodIso8601Serializer) datePeriodIso8601Serialization(DatePeriodIso8601Serializer, DateTimePeriodIso8601Serializer) } @Test fun testDatePeriodComponentSerialization() { + assertKSerializerName("kotlinx.datetime.DatePeriod", DatePeriodComponentSerializer) datePeriodComponentSerialization(DatePeriodComponentSerializer, DateTimePeriodComponentSerializer) } @Test fun testDateTimePeriodIso8601Serialization() { + assertKSerializerName("kotlinx.datetime.DateTimePeriod", DateTimePeriodIso8601Serializer) dateTimePeriodIso8601Serialization(DateTimePeriodIso8601Serializer) } @Test fun testDateTimePeriodComponentSerialization() { + assertKSerializerName("kotlinx.datetime.DateTimePeriod", DateTimePeriodComponentSerializer) dateTimePeriodComponentSerialization(DateTimePeriodComponentSerializer) } @Test fun testDefaultSerializers() { // Check that they behave the same as the ISO 8601 serializers + assertKSerializerName("kotlinx.datetime.DateTimePeriod", Json.serializersModule.serializer()) dateTimePeriodIso8601Serialization(Json.serializersModule.serializer()) + assertKSerializerName("kotlinx.datetime.DatePeriod", Json.serializersModule.serializer()) datePeriodIso8601Serialization(Json.serializersModule.serializer(), Json.serializersModule.serializer()) } diff --git a/serialization/common/test/DateTimeUnitSerializationTest.kt b/serialization/common/test/DateTimeUnitSerializationTest.kt index e2b4f8b6e..39e57a255 100644 --- a/serialization/common/test/DateTimeUnitSerializationTest.kt +++ b/serialization/common/test/DateTimeUnitSerializationTest.kt @@ -18,7 +18,7 @@ class DateTimeUnitSerializationTest { repeat(100) { val nanoseconds = Random.nextLong(1, Long.MAX_VALUE) val unit = DateTimeUnit.TimeBased(nanoseconds) - val json = "{\"nanoseconds\":${nanoseconds.toString()}}" // https://youtrack.jetbrains.com/issue/KT-39891 + val json = "{\"nanoseconds\":$nanoseconds}" assertEquals(json, Json.encodeToString(serializer, unit)) assertEquals(unit, Json.decodeFromString(serializer, json)) } @@ -65,7 +65,7 @@ class DateTimeUnitSerializationTest { repeat(100) { val nanoseconds = Random.nextLong(1, Long.MAX_VALUE) val unit = DateTimeUnit.TimeBased(nanoseconds) - val json = "{\"type\":\"kotlinx.datetime.TimeBased\",\"nanoseconds\":${nanoseconds.toString()}}" // https://youtrack.jetbrains.com/issue/KT-39891 + val json = "{\"type\":\"kotlinx.datetime.TimeBased\",\"nanoseconds\":$nanoseconds}" assertEquals(json, Json.encodeToString(serializer, unit)) assertEquals(unit, Json.decodeFromString(serializer, json)) } @@ -87,21 +87,25 @@ class DateTimeUnitSerializationTest { @Test fun testTimeBasedUnitSerialization() { + assertKSerializerName("kotlinx.datetime.TimeBased", TimeBasedDateTimeUnitSerializer) timeBasedSerialization(TimeBasedDateTimeUnitSerializer) } @Test fun testDayBasedSerialization() { + assertKSerializerName("kotlinx.datetime.DayBased", DayBasedDateTimeUnitSerializer) dayBasedSerialization(DayBasedDateTimeUnitSerializer) } @Test fun testMonthBasedSerialization() { + assertKSerializerName("kotlinx.datetime.MonthBased", MonthBasedDateTimeUnitSerializer) monthBasedSerialization(MonthBasedDateTimeUnitSerializer) } @Test fun testDateBasedSerialization() { + assertKSerializerName("kotlinx.datetime.DateTimeUnit.DateBased", DateBasedDateTimeUnitSerializer) dateBasedSerialization(DateBasedDateTimeUnitSerializer) } diff --git a/serialization/common/test/DayOfWeekSerializationTest.kt b/serialization/common/test/DayOfWeekSerializationTest.kt index aa81e8acf..70eb35a94 100644 --- a/serialization/common/test/DayOfWeekSerializationTest.kt +++ b/serialization/common/test/DayOfWeekSerializationTest.kt @@ -13,10 +13,11 @@ import kotlin.test.* class DayOfWeekSerializationTest { @Test fun testSerialization() { + assertKSerializerName("kotlinx.datetime.DayOfWeek", DayOfWeekSerializer) for (dayOfWeek in DayOfWeek.entries) { val json = "\"${dayOfWeek.name}\"" assertEquals(json, Json.encodeToString(DayOfWeekSerializer, dayOfWeek)) assertEquals(dayOfWeek, Json.decodeFromString(DayOfWeekSerializer, json)) } } -} \ No newline at end of file +} diff --git a/serialization/common/test/InstantSerializationTest.kt b/serialization/common/test/InstantSerializationTest.kt index ed0919e27..6c848bbd4 100644 --- a/serialization/common/test/InstantSerializationTest.kt +++ b/serialization/common/test/InstantSerializationTest.kt @@ -54,17 +54,20 @@ class InstantSerializationTest { @Test fun testIso8601Serialization() { + assertKSerializerName("kotlinx.datetime.Instant", InstantIso8601Serializer) iso8601Serialization(InstantIso8601Serializer) } @Test fun testComponentSerialization() { + assertKSerializerName("kotlinx.datetime.Instant", InstantComponentSerializer) componentSerialization(InstantComponentSerializer) } @Test fun testDefaultSerializers() { // should be the same as the ISO 8601 + assertKSerializerName("kotlinx.datetime.Instant", Json.serializersModule.serializer()) iso8601Serialization(Json.serializersModule.serializer()) } diff --git a/serialization/common/test/LocalDateSerializationTest.kt b/serialization/common/test/LocalDateSerializationTest.kt index c6ca20136..bd6dd9517 100644 --- a/serialization/common/test/LocalDateSerializationTest.kt +++ b/serialization/common/test/LocalDateSerializationTest.kt @@ -56,17 +56,20 @@ class LocalDateSerializationTest { @Test fun testIso8601Serialization() { + assertKSerializerName("kotlinx.datetime.LocalDate", LocalDateIso8601Serializer) iso8601Serialization(LocalDateIso8601Serializer) } @Test fun testComponentSerialization() { + assertKSerializerName("kotlinx.datetime.LocalDate", LocalDateComponentSerializer) componentSerialization(LocalDateComponentSerializer) } @Test fun testDefaultSerializers() { // should be the same as the ISO 8601 + assertKSerializerName("kotlinx.datetime.LocalDate", Json.serializersModule.serializer()) iso8601Serialization(Json.serializersModule.serializer()) } diff --git a/serialization/common/test/LocalDateTimeSerializationTest.kt b/serialization/common/test/LocalDateTimeSerializationTest.kt index e780ed397..0520d3f06 100644 --- a/serialization/common/test/LocalDateTimeSerializationTest.kt +++ b/serialization/common/test/LocalDateTimeSerializationTest.kt @@ -70,17 +70,20 @@ class LocalDateTimeSerializationTest { @Test fun testIso8601Serialization() { + assertKSerializerName("kotlinx.datetime.LocalDateTime", LocalDateTimeComponentSerializer) iso8601Serialization(LocalDateTimeIso8601Serializer) } @Test fun testComponentSerialization() { + assertKSerializerName("kotlinx.datetime.LocalDateTime", LocalDateTimeComponentSerializer) componentSerialization(LocalDateTimeComponentSerializer) } @Test fun testDefaultSerializers() { // should be the same as the ISO 8601 + assertKSerializerName("kotlinx.datetime.LocalDateTime", Json.serializersModule.serializer()) iso8601Serialization(Json.serializersModule.serializer()) } diff --git a/serialization/common/test/LocalTimeSerializationTest.kt b/serialization/common/test/LocalTimeSerializationTest.kt index 9cf423998..f1af3b276 100644 --- a/serialization/common/test/LocalTimeSerializationTest.kt +++ b/serialization/common/test/LocalTimeSerializationTest.kt @@ -60,17 +60,20 @@ class LocalTimeSerializationTest { @Test fun testIso8601Serialization() { + assertKSerializerName("kotlinx.datetime.LocalTime", LocalTimeIso8601Serializer) iso8601Serialization(LocalTimeIso8601Serializer) } @Test fun testComponentSerialization() { + assertKSerializerName("kotlinx.datetime.LocalTime", LocalTimeComponentSerializer) componentSerialization(LocalTimeComponentSerializer) } @Test fun testDefaultSerializers() { // should be the same as the ISO 8601 + assertKSerializerName("kotlinx.datetime.LocalTime", Json.serializersModule.serializer()) iso8601Serialization(Json.serializersModule.serializer()) } diff --git a/serialization/common/test/MonthSerializationTest.kt b/serialization/common/test/MonthSerializationTest.kt index 3296ba080..70d9b4552 100644 --- a/serialization/common/test/MonthSerializationTest.kt +++ b/serialization/common/test/MonthSerializationTest.kt @@ -13,10 +13,11 @@ import kotlin.test.* class MonthSerializationTest { @Test fun testSerialization() { + assertKSerializerName("kotlinx.datetime.Month", MonthSerializer) for (month in Month.entries) { val json = "\"${month.name}\"" assertEquals(json, Json.encodeToString(MonthSerializer, month)) assertEquals(month, Json.decodeFromString(MonthSerializer, json)) } } -} \ No newline at end of file +} diff --git a/serialization/common/test/TimeZoneSerializationTest.kt b/serialization/common/test/TimeZoneSerializationTest.kt index f4062b0b9..b34f5633d 100644 --- a/serialization/common/test/TimeZoneSerializationTest.kt +++ b/serialization/common/test/TimeZoneSerializationTest.kt @@ -46,7 +46,11 @@ class TimeZoneSerializationTest { @Test fun testDefaultSerializers() { + assertKSerializerName( + "kotlinx.datetime.FixedOffsetTimeZone", Json.serializersModule.serializer() + ) zoneOffsetSerialization(Json.serializersModule.serializer()) + assertKSerializerName("kotlinx.datetime.TimeZone", Json.serializersModule.serializer()) serialization(Json.serializersModule.serializer()) } -} \ No newline at end of file +} diff --git a/serialization/common/test/UtcOffsetSerializationTest.kt b/serialization/common/test/UtcOffsetSerializationTest.kt index 5c2064e7a..687c62b9a 100644 --- a/serialization/common/test/UtcOffsetSerializationTest.kt +++ b/serialization/common/test/UtcOffsetSerializationTest.kt @@ -27,11 +27,13 @@ class UtcOffsetSerializationTest { @Test fun defaultSerializer() { + assertKSerializerName("kotlinx.datetime.UtcOffset", Json.serializersModule.serializer()) testSerializationAsPrimitive(Json.serializersModule.serializer()) } @Test fun stringPrimitiveSerializer() { + assertKSerializerName("kotlinx.datetime.UtcOffset", UtcOffsetSerializer) testSerializationAsPrimitive(UtcOffsetSerializer) testSerializationAsPrimitive(UtcOffset.serializer()) } From 0f5f48ea6e631f6c750f6c2319c4b05a0e4dca51 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Mon, 13 May 2024 15:47:12 +0200 Subject: [PATCH 5/7] Separate ISO and default serializers Sometimes, `X.Formats.ISO` and `X.parse()`/`X.toString()` behave subtly differently; currently, it's the case for `LocalDateTime` and `LocalTime`. With this change, every entity that supports custom formats obtains a separate default serializer in addition to the ISO 8601 serializer, which now properly delegates to the corresponding `DateTimeFormat`. Fixes #351 --- core/common/src/Instant.kt | 6 +-- core/common/src/LocalDate.kt | 3 +- core/common/src/LocalDateTime.kt | 6 +-- core/common/src/LocalTime.kt | 6 +-- core/common/src/UtcOffset.kt | 6 ++- .../src/serializers/InstantSerializers.kt | 26 ++++++++-- .../src/serializers/LocalDateSerializers.kt | 38 ++++++++------ .../serializers/LocalDateTimeSerializers.kt | 38 ++++++++------ .../src/serializers/LocalTimeSerializers.kt | 39 +++++++++----- .../src/serializers/TimeZoneSerializers.kt | 12 ++++- core/commonKotlin/src/Instant.kt | 4 +- core/commonKotlin/src/LocalDate.kt | 4 +- core/commonKotlin/src/LocalDateTime.kt | 2 +- core/commonKotlin/src/LocalTime.kt | 4 +- core/commonKotlin/src/UtcOffset.kt | 3 +- core/jvm/src/Instant.kt | 4 +- core/jvm/src/LocalDate.kt | 4 +- core/jvm/src/LocalDateTimeJvm.kt | 4 +- core/jvm/src/LocalTimeJvm.kt | 4 +- core/jvm/src/UtcOffsetJvm.kt | 3 +- .../common/test/InstantSerializationTest.kt | 26 ++++++++-- .../test/LocalDateTimeSerializationTest.kt | 15 +++++- .../common/test/LocalTimeSerializationTest.kt | 16 +++++- .../common/test/UtcOffsetSerializationTest.kt | 52 +++++++++++++------ 24 files changed, 223 insertions(+), 102 deletions(-) diff --git a/core/common/src/Instant.kt b/core/common/src/Instant.kt index 3deedd946..edf9425fb 100644 --- a/core/common/src/Instant.kt +++ b/core/common/src/Instant.kt @@ -7,8 +7,7 @@ package kotlinx.datetime import kotlinx.datetime.format.* import kotlinx.datetime.internal.* -import kotlinx.datetime.serializers.InstantIso8601Serializer -import kotlinx.datetime.serializers.InstantComponentSerializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import kotlin.time.* @@ -189,12 +188,13 @@ import kotlin.time.* * ``` * * Additionally, there are several `kotlinx-serialization` serializers for [Instant]: + * - The default serializer, delegating to [toString] and [parse]. * - [InstantIso8601Serializer] for the ISO 8601 extended format. * - [InstantComponentSerializer] for an object with components. * * @see LocalDateTime for a user-visible representation of moments in time in an unspecified time zone. */ -@Serializable(with = InstantIso8601Serializer::class) +@Serializable(with = InstantSerializer::class) public expect class Instant : Comparable { /** diff --git a/core/common/src/LocalDate.kt b/core/common/src/LocalDate.kt index 5225f2bef..68a5bfed5 100644 --- a/core/common/src/LocalDate.kt +++ b/core/common/src/LocalDate.kt @@ -57,6 +57,7 @@ import kotlin.internal.* * See sample 4. * * Additionally, there are several `kotlinx-serialization` serializers for [LocalDate]: + * - The default serializer, delegating to [toString] and [parse]. * - [LocalDateIso8601Serializer] for the ISO 8601 extended format. * - [LocalDateComponentSerializer] for an object with components. * @@ -65,7 +66,7 @@ import kotlin.internal.* * @sample kotlinx.datetime.test.samples.LocalDateSamples.simpleParsingAndFormatting * @sample kotlinx.datetime.test.samples.LocalDateSamples.customFormat */ -@Serializable(with = LocalDateIso8601Serializer::class) +@Serializable(with = LocalDateSerializer::class) public expect class LocalDate : Comparable { public companion object { /** diff --git a/core/common/src/LocalDateTime.kt b/core/common/src/LocalDateTime.kt index 8e5085ca4..a6569df3a 100644 --- a/core/common/src/LocalDateTime.kt +++ b/core/common/src/LocalDateTime.kt @@ -8,8 +8,7 @@ package kotlinx.datetime import kotlinx.datetime.format.* -import kotlinx.datetime.serializers.LocalDateTimeIso8601Serializer -import kotlinx.datetime.serializers.LocalDateTimeComponentSerializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import kotlin.internal.* import kotlin.jvm.JvmMultifileClass @@ -99,6 +98,7 @@ import kotlin.jvm.JvmName * See sample 4. * * Additionally, there are several `kotlinx-serialization` serializers for [LocalDateTime]: + * - The default serializer, delegating to [toString] and [parse]. * - [LocalDateTimeIso8601Serializer] for the ISO 8601 extended format. * - [LocalDateTimeComponentSerializer] for an object with components. * @@ -110,7 +110,7 @@ import kotlin.jvm.JvmName * @sample kotlinx.datetime.test.samples.LocalDateTimeSamples.simpleParsingAndFormatting * @sample kotlinx.datetime.test.samples.LocalDateTimeSamples.customFormat */ -@Serializable(with = LocalDateTimeIso8601Serializer::class) +@Serializable(with = LocalDateTimeSerializer::class) public expect class LocalDateTime : Comparable { public companion object { diff --git a/core/common/src/LocalTime.kt b/core/common/src/LocalTime.kt index 4c2154e77..219a58f67 100644 --- a/core/common/src/LocalTime.kt +++ b/core/common/src/LocalTime.kt @@ -8,8 +8,7 @@ package kotlinx.datetime import kotlinx.datetime.format.* -import kotlinx.datetime.serializers.LocalTimeIso8601Serializer -import kotlinx.datetime.serializers.LocalTimeComponentSerializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import kotlin.internal.* import kotlin.jvm.JvmMultifileClass @@ -72,6 +71,7 @@ import kotlin.jvm.JvmName * See sample 4. * * Additionally, there are several `kotlinx-serialization` serializers for [LocalTime]: + * - The default serializer, delegating to [toString] and [parse]. * - [LocalTimeIso8601Serializer] for the ISO 8601 extended format, * - [LocalTimeComponentSerializer] for an object with components. * @@ -80,7 +80,7 @@ import kotlin.jvm.JvmName * @sample kotlinx.datetime.test.samples.LocalTimeSamples.simpleParsingAndFormatting * @sample kotlinx.datetime.test.samples.LocalTimeSamples.customFormat */ -@Serializable(LocalTimeIso8601Serializer::class) +@Serializable(LocalTimeSerializer::class) public expect class LocalTime : Comparable { public companion object { diff --git a/core/common/src/UtcOffset.kt b/core/common/src/UtcOffset.kt index 97c5e4103..8a5cc7696 100644 --- a/core/common/src/UtcOffset.kt +++ b/core/common/src/UtcOffset.kt @@ -6,7 +6,7 @@ package kotlinx.datetime import kotlinx.datetime.format.* -import kotlinx.datetime.serializers.UtcOffsetSerializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable /** @@ -47,12 +47,14 @@ import kotlinx.serialization.Serializable * [parse] and [UtcOffset.format] both support custom formats created with [Format] or defined in [Formats]. * See sample 3. * - * To serialize and deserialize [UtcOffset] values with `kotlinx-serialization`, use the [UtcOffsetSerializer]. + * To serialize and deserialize [UtcOffset] values with `kotlinx-serialization`, use the default serializer, + * or [UtcOffsetIso8601Serializer] for the ISO 8601 format explicitly. * * @sample kotlinx.datetime.test.samples.UtcOffsetSamples.construction * @sample kotlinx.datetime.test.samples.UtcOffsetSamples.simpleParsingAndFormatting * @sample kotlinx.datetime.test.samples.UtcOffsetSamples.customFormat */ +@Suppress("DEPRECATION") @Serializable(with = UtcOffsetSerializer::class) public expect class UtcOffset { /** diff --git a/core/common/src/serializers/InstantSerializers.kt b/core/common/src/serializers/InstantSerializers.kt index 3e5db5a9a..e46a0c449 100644 --- a/core/common/src/serializers/InstantSerializers.kt +++ b/core/common/src/serializers/InstantSerializers.kt @@ -17,8 +17,7 @@ import kotlinx.serialization.encoding.* * * JSON example: `"2020-12-09T09:16:56.000124Z"` * - * @see Instant.toString - * @see Instant.parse + * @see DateTimeComponents.Formats.ISO_DATE_TIME_OFFSET */ public object InstantIso8601Serializer : KSerializer { @@ -26,10 +25,10 @@ public object InstantIso8601Serializer : KSerializer { PrimitiveSerialDescriptor("kotlinx.datetime.Instant", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): Instant = - Instant.parse(decoder.decodeString()) + Instant.parse(decoder.decodeString(), DateTimeComponents.Formats.ISO_DATE_TIME_OFFSET) override fun serialize(encoder: Encoder, value: Instant) { - encoder.encodeString(value.toString()) + encoder.encodeString(value.format(DateTimeComponents.Formats.ISO_DATE_TIME_OFFSET)) } } @@ -125,3 +124,22 @@ public abstract class FormattedInstantSerializer( @OptIn(ExperimentalSerializationApi::class) override fun toString(): String = descriptor.serialName } + +/** + * A serializer for [Instant] that uses the default [Instant.toString]/[Instant.parse]. + * + * JSON example: `"2020-12-09T09:16:56.000124Z"` + */ +@PublishedApi internal object InstantSerializer : KSerializer { + + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("kotlinx.datetime.Instant", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): Instant = + Instant.parse(decoder.decodeString()) + + override fun serialize(encoder: Encoder, value: Instant) { + encoder.encodeString(value.toString()) + } + +} diff --git a/core/common/src/serializers/LocalDateSerializers.kt b/core/common/src/serializers/LocalDateSerializers.kt index 6618246eb..83ff40226 100644 --- a/core/common/src/serializers/LocalDateSerializers.kt +++ b/core/common/src/serializers/LocalDateSerializers.kt @@ -16,22 +16,10 @@ import kotlinx.serialization.encoding.* * * JSON example: `"2020-01-01"` * - * @see LocalDate.parse - * @see LocalDate.toString + * @see LocalDate.Formats.ISO */ -public object LocalDateIso8601Serializer: KSerializer { - - override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("kotlinx.datetime.LocalDate", PrimitiveKind.STRING) - - override fun deserialize(decoder: Decoder): LocalDate = - LocalDate.parse(decoder.decodeString()) - - override fun serialize(encoder: Encoder, value: LocalDate) { - encoder.encodeString(value.toString()) - } - -} +public object LocalDateIso8601Serializer : KSerializer +by LocalDate.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDate") /** * A serializer for [LocalDate] that represents a value as its components. @@ -117,3 +105,23 @@ internal fun DateTimeFormat.asKSerializer(serialName: String): KSerialize override fun toString(): String = serialName } + +/** + * A serializer for [LocalDate] that uses the default [LocalDate.toString]/[LocalDate.parse]. + * + * JSON example: `"2020-01-01"` + */ +@PublishedApi +internal object LocalDateSerializer: KSerializer { + + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("kotlinx.datetime.LocalDate", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): LocalDate = + LocalDate.parse(decoder.decodeString()) + + override fun serialize(encoder: Encoder, value: LocalDate) { + encoder.encodeString(value.toString()) + } + +} diff --git a/core/common/src/serializers/LocalDateTimeSerializers.kt b/core/common/src/serializers/LocalDateTimeSerializers.kt index 4b6a86536..cb0f89bd8 100644 --- a/core/common/src/serializers/LocalDateTimeSerializers.kt +++ b/core/common/src/serializers/LocalDateTimeSerializers.kt @@ -16,22 +16,10 @@ import kotlinx.serialization.encoding.* * * JSON example: `"2007-12-31T23:59:01"` * - * @see LocalDateTime.parse - * @see LocalDateTime.toString + * @see LocalDateTime.Formats.ISO */ -public object LocalDateTimeIso8601Serializer: KSerializer { - - override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("kotlinx.datetime.LocalDateTime", PrimitiveKind.STRING) - - override fun deserialize(decoder: Decoder): LocalDateTime = - LocalDateTime.parse(decoder.decodeString()) - - override fun serialize(encoder: Encoder, value: LocalDateTime) { - encoder.encodeString(value.toString()) - } - -} +public object LocalDateTimeIso8601Serializer : KSerializer +by LocalDateTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDateTime") /** * A serializer for [LocalDateTime] that represents a value as its components. @@ -130,3 +118,23 @@ public object LocalDateTimeComponentSerializer: KSerializer { public abstract class FormattedLocalDateTimeSerializer( name: String, format: DateTimeFormat ) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalDateTime serializer $name") + +/** + * A serializer for [LocalDateTime] that uses the default [LocalDateTime.toString]/[LocalDateTime.parse]. + * + * JSON example: `"2007-12-31T23:59:01"` + */ +@PublishedApi +internal object LocalDateTimeSerializer: KSerializer { + + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("kotlinx.datetime.LocalDateTime", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): LocalDateTime = + LocalDateTime.parse(decoder.decodeString()) + + override fun serialize(encoder: Encoder, value: LocalDateTime) { + encoder.encodeString(value.toString()) + } + +} diff --git a/core/common/src/serializers/LocalTimeSerializers.kt b/core/common/src/serializers/LocalTimeSerializers.kt index 10a3750e2..0b86050b3 100644 --- a/core/common/src/serializers/LocalTimeSerializers.kt +++ b/core/common/src/serializers/LocalTimeSerializers.kt @@ -16,21 +16,10 @@ import kotlinx.serialization.encoding.* * * JSON example: `"12:01:03.999"` * - * @see LocalDate.parse - * @see LocalDate.toString + * @see LocalTime.Formats.ISO */ -public object LocalTimeIso8601Serializer : KSerializer { - - override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("kotlinx.datetime.LocalTime", PrimitiveKind.STRING) - - override fun deserialize(decoder: Decoder): LocalTime = - LocalTime.parse(decoder.decodeString()) - - override fun serialize(encoder: Encoder, value: LocalTime) { - encoder.encodeString(value.toString()) - } -} +public object LocalTimeIso8601Serializer : KSerializer +by LocalTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalTime") /** * A serializer for [LocalTime] that represents a value as its components. @@ -109,3 +98,25 @@ public object LocalTimeComponentSerializer : KSerializer { public abstract class FormattedLocalTimeSerializer( name: String, format: DateTimeFormat ) : KSerializer by format.asKSerializer("kotlinx.datetime.LocalTime serializer $name") + +/** + * A serializer for [LocalTime] that uses the ISO 8601 representation. + * + * JSON example: `"12:01:03.999"` + * + * @see LocalDate.parse + * @see LocalDate.toString + */ +@PublishedApi +internal object LocalTimeSerializer : KSerializer { + + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("kotlinx.datetime.LocalTime", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): LocalTime = + LocalTime.parse(decoder.decodeString()) + + override fun serialize(encoder: Encoder, value: LocalTime) { + encoder.encodeString(value.toString()) + } +} diff --git a/core/common/src/serializers/TimeZoneSerializers.kt b/core/common/src/serializers/TimeZoneSerializers.kt index b0d5c5071..f9281809a 100644 --- a/core/common/src/serializers/TimeZoneSerializers.kt +++ b/core/common/src/serializers/TimeZoneSerializers.kt @@ -57,9 +57,17 @@ public object FixedOffsetTimeZoneSerializer: KSerializer { * * JSON example: `"+02:00"` * - * @see UtcOffset.parse - * @see UtcOffset.toString + * @see UtcOffset.Formats.ISO */ +public object UtcOffsetIso8601Serializer : KSerializer +by UtcOffset.Formats.ISO.asKSerializer("kotlinx.datetime.UtcOffset") + +/** + * A serializer for [UtcOffset] that uses the default [UtcOffset.toString]/[UtcOffset.parse]. + * + * JSON example: `"+02:00"` + */ +@Deprecated("Use UtcOffset.serializer() instead", ReplaceWith("UtcOffset.serializer()")) public object UtcOffsetSerializer: KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("kotlinx.datetime.UtcOffset", PrimitiveKind.STRING) diff --git a/core/commonKotlin/src/Instant.kt b/core/commonKotlin/src/Instant.kt index b4cff744c..7a9696ba5 100644 --- a/core/commonKotlin/src/Instant.kt +++ b/core/commonKotlin/src/Instant.kt @@ -10,7 +10,7 @@ package kotlinx.datetime import kotlinx.datetime.format.* import kotlinx.datetime.internal.* -import kotlinx.datetime.serializers.InstantIso8601Serializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import kotlin.time.* import kotlin.time.Duration.Companion.nanoseconds @@ -26,7 +26,7 @@ private const val MIN_SECOND = -31557014167219200L // -1000000000-01-01T00:00:00 */ private const val MAX_SECOND = 31556889864403199L // +1000000000-12-31T23:59:59 -@Serializable(with = InstantIso8601Serializer::class) +@Serializable(with = InstantSerializer::class) public actual class Instant internal constructor(public actual val epochSeconds: Long, public actual val nanosecondsOfSecond: Int) : Comparable { init { diff --git a/core/commonKotlin/src/LocalDate.kt b/core/commonKotlin/src/LocalDate.kt index 147b89cd7..f2e60accf 100644 --- a/core/commonKotlin/src/LocalDate.kt +++ b/core/commonKotlin/src/LocalDate.kt @@ -12,7 +12,7 @@ import kotlinx.datetime.format.* import kotlinx.datetime.internal.* import kotlinx.datetime.internal.safeAdd import kotlinx.datetime.internal.safeMultiply -import kotlinx.datetime.serializers.LocalDateIso8601Serializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import kotlin.math.* @@ -22,7 +22,7 @@ internal const val YEAR_MAX = 999_999_999 private fun isValidYear(year: Int): Boolean = year >= YEAR_MIN && year <= YEAR_MAX -@Serializable(with = LocalDateIso8601Serializer::class) +@Serializable(with = LocalDateSerializer::class) public actual class LocalDate actual constructor(public actual val year: Int, month: Int, public actual val day: Int) : Comparable { private val _month: Int = month diff --git a/core/commonKotlin/src/LocalDateTime.kt b/core/commonKotlin/src/LocalDateTime.kt index 9375ae91b..4a7e23853 100644 --- a/core/commonKotlin/src/LocalDateTime.kt +++ b/core/commonKotlin/src/LocalDateTime.kt @@ -13,7 +13,7 @@ import kotlinx.datetime.internal.* import kotlinx.datetime.serializers.* import kotlinx.serialization.* -@Serializable(with = LocalDateTimeIso8601Serializer::class) +@Serializable(with = LocalDateTimeSerializer::class) public actual class LocalDateTime public actual constructor(public actual val date: LocalDate, public actual val time: LocalTime) : Comparable { public actual companion object { diff --git a/core/commonKotlin/src/LocalTime.kt b/core/commonKotlin/src/LocalTime.kt index 28ebd78df..42f5c0177 100644 --- a/core/commonKotlin/src/LocalTime.kt +++ b/core/commonKotlin/src/LocalTime.kt @@ -10,10 +10,10 @@ package kotlinx.datetime import kotlinx.datetime.internal.* import kotlinx.datetime.format.* -import kotlinx.datetime.serializers.LocalTimeIso8601Serializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable -@Serializable(LocalTimeIso8601Serializer::class) +@Serializable(LocalTimeSerializer::class) public actual class LocalTime actual constructor( public actual val hour: Int, public actual val minute: Int, diff --git a/core/commonKotlin/src/UtcOffset.kt b/core/commonKotlin/src/UtcOffset.kt index e8329d0c7..e947e88fd 100644 --- a/core/commonKotlin/src/UtcOffset.kt +++ b/core/commonKotlin/src/UtcOffset.kt @@ -7,11 +7,12 @@ package kotlinx.datetime import kotlinx.datetime.internal.* import kotlinx.datetime.format.* -import kotlinx.datetime.serializers.UtcOffsetSerializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import kotlin.math.abs import kotlin.native.concurrent.ThreadLocal +@Suppress("DEPRECATION") @Serializable(with = UtcOffsetSerializer::class) public actual class UtcOffset private constructor(public actual val totalSeconds: Int) { diff --git a/core/jvm/src/Instant.kt b/core/jvm/src/Instant.kt index 78f82ed8b..735ce53df 100644 --- a/core/jvm/src/Instant.kt +++ b/core/jvm/src/Instant.kt @@ -9,7 +9,7 @@ package kotlinx.datetime import kotlinx.datetime.format.* import kotlinx.datetime.internal.safeMultiply import kotlinx.datetime.internal.* -import kotlinx.datetime.serializers.InstantIso8601Serializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import java.time.DateTimeException import java.time.temporal.* @@ -19,7 +19,7 @@ import kotlin.time.Duration.Companion.seconds import java.time.Instant as jtInstant import java.time.Clock as jtClock -@Serializable(with = InstantIso8601Serializer::class) +@Serializable(with = InstantSerializer::class) public actual class Instant internal constructor( internal val value: jtInstant ) : Comparable { diff --git a/core/jvm/src/LocalDate.kt b/core/jvm/src/LocalDate.kt index 7e7cda702..7e87580b3 100644 --- a/core/jvm/src/LocalDate.kt +++ b/core/jvm/src/LocalDate.kt @@ -9,7 +9,7 @@ import kotlinx.datetime.format.* import kotlinx.datetime.internal.safeAdd import kotlinx.datetime.internal.safeMultiply import kotlinx.datetime.internal.* -import kotlinx.datetime.serializers.LocalDateIso8601Serializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import java.time.DateTimeException import java.time.format.DateTimeParseException @@ -17,7 +17,7 @@ import java.time.temporal.ChronoUnit import java.time.LocalDate as jtLocalDate import kotlin.internal.* -@Serializable(with = LocalDateIso8601Serializer::class) +@Serializable(with = LocalDateSerializer::class) public actual class LocalDate internal constructor( internal val value: jtLocalDate ) : Comparable, java.io.Serializable { diff --git a/core/jvm/src/LocalDateTimeJvm.kt b/core/jvm/src/LocalDateTimeJvm.kt index 235be9071..30a710af2 100644 --- a/core/jvm/src/LocalDateTimeJvm.kt +++ b/core/jvm/src/LocalDateTimeJvm.kt @@ -8,13 +8,13 @@ package kotlinx.datetime import kotlinx.datetime.format.* import kotlinx.datetime.internal.removeLeadingZerosFromLongYearFormLocalDateTime -import kotlinx.datetime.serializers.LocalDateTimeIso8601Serializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import java.time.DateTimeException import java.time.format.DateTimeParseException import java.time.LocalDateTime as jtLocalDateTime -@Serializable(with = LocalDateTimeIso8601Serializer::class) +@Serializable(with = LocalDateTimeSerializer::class) public actual class LocalDateTime internal constructor( internal val value: jtLocalDateTime ) : Comparable, java.io.Serializable { diff --git a/core/jvm/src/LocalTimeJvm.kt b/core/jvm/src/LocalTimeJvm.kt index 98f42011b..9d815fe15 100644 --- a/core/jvm/src/LocalTimeJvm.kt +++ b/core/jvm/src/LocalTimeJvm.kt @@ -9,13 +9,13 @@ package kotlinx.datetime import kotlinx.datetime.format.* import kotlinx.datetime.internal.* -import kotlinx.datetime.serializers.LocalTimeIso8601Serializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import java.time.DateTimeException import java.time.format.DateTimeParseException import java.time.LocalTime as jtLocalTime -@Serializable(with = LocalTimeIso8601Serializer::class) +@Serializable(with = LocalTimeSerializer::class) public actual class LocalTime internal constructor( internal val value: jtLocalTime ) : Comparable, java.io.Serializable { diff --git a/core/jvm/src/UtcOffsetJvm.kt b/core/jvm/src/UtcOffsetJvm.kt index 7f9ed7031..40908fb33 100644 --- a/core/jvm/src/UtcOffsetJvm.kt +++ b/core/jvm/src/UtcOffsetJvm.kt @@ -6,13 +6,14 @@ package kotlinx.datetime import kotlinx.datetime.format.* -import kotlinx.datetime.serializers.UtcOffsetSerializer +import kotlinx.datetime.serializers.* import kotlinx.serialization.Serializable import java.time.DateTimeException import java.time.ZoneOffset import java.time.format.DateTimeFormatterBuilder import java.time.format.* +@Suppress("DEPRECATION") @Serializable(with = UtcOffsetSerializer::class) public actual class UtcOffset( internal val zoneOffset: ZoneOffset diff --git a/serialization/common/test/InstantSerializationTest.kt b/serialization/common/test/InstantSerializationTest.kt index 6c848bbd4..6d83dc0b1 100644 --- a/serialization/common/test/InstantSerializationTest.kt +++ b/serialization/common/test/InstantSerializationTest.kt @@ -15,10 +15,26 @@ class InstantSerializationTest { private fun iso8601Serialization(serializer: KSerializer) { for ((instant, json) in listOf( - Pair(Instant.fromEpochSeconds(1607505416, 124000), - "\"2020-12-09T09:16:56.000124Z\""), - Pair(Instant.fromEpochSeconds(-1607505416, -124000), - "\"1919-01-23T14:43:03.999876Z\""), + Pair(Instant.fromEpochSeconds(1607505416, 120000), + "\"2020-12-09T09:16:56.00012Z\""), + Pair(Instant.fromEpochSeconds(-1607505416, -120000), + "\"1919-01-23T14:43:03.99988Z\""), + Pair(Instant.fromEpochSeconds(987654321, 123456789), + "\"2001-04-19T04:25:21.123456789Z\""), + Pair(Instant.fromEpochSeconds(987654321, 0), + "\"2001-04-19T04:25:21Z\""), + )) { + assertEquals(json, Json.encodeToString(serializer, instant)) + assertEquals(instant, Json.decodeFromString(serializer, json)) + } + } + + private fun defaultSerialization(serializer: KSerializer) { + for ((instant, json) in listOf( + Pair(Instant.fromEpochSeconds(1607505416, 120000), + "\"2020-12-09T09:16:56.000120Z\""), + Pair(Instant.fromEpochSeconds(-1607505416, -120000), + "\"1919-01-23T14:43:03.999880Z\""), Pair(Instant.fromEpochSeconds(987654321, 123456789), "\"2001-04-19T04:25:21.123456789Z\""), Pair(Instant.fromEpochSeconds(987654321, 0), @@ -68,7 +84,7 @@ class InstantSerializationTest { fun testDefaultSerializers() { // should be the same as the ISO 8601 assertKSerializerName("kotlinx.datetime.Instant", Json.serializersModule.serializer()) - iso8601Serialization(Json.serializersModule.serializer()) + defaultSerialization(Json.serializersModule.serializer()) } object Rfc1123InstantSerializer : FormattedInstantSerializer("RFC_1123", DateTimeComponents.Formats.RFC_1123) diff --git a/serialization/common/test/LocalDateTimeSerializationTest.kt b/serialization/common/test/LocalDateTimeSerializationTest.kt index 0520d3f06..63649a341 100644 --- a/serialization/common/test/LocalDateTimeSerializationTest.kt +++ b/serialization/common/test/LocalDateTimeSerializationTest.kt @@ -15,6 +15,19 @@ import kotlin.test.* class LocalDateTimeSerializationTest { private fun iso8601Serialization(serializer: KSerializer) { + for ((localDateTime, json) in listOf( + Pair(LocalDateTime(2008, 7, 5, 2, 1), "\"2008-07-05T02:01:00\""), + Pair(LocalDateTime(2007, 12, 31, 23, 59, 1), "\"2007-12-31T23:59:01\""), + Pair(LocalDateTime(999, 12, 31, 23, 59, 59, 990000000), "\"0999-12-31T23:59:59.99\""), + Pair(LocalDateTime(-1, 1, 2, 23, 59, 59, 999990000), "\"-0001-01-02T23:59:59.99999\""), + Pair(LocalDateTime(-2008, 1, 2, 23, 59, 59, 999999990), "\"-2008-01-02T23:59:59.99999999\""), + )) { + assertEquals(json, Json.encodeToString(serializer, localDateTime)) + assertEquals(localDateTime, Json.decodeFromString(serializer, json)) + } + } + + private fun defaultSerialization(serializer: KSerializer) { for ((localDateTime, json) in listOf( Pair(LocalDateTime(2008, 7, 5, 2, 1), "\"2008-07-05T02:01\""), Pair(LocalDateTime(2007, 12, 31, 23, 59, 1), "\"2007-12-31T23:59:01\""), @@ -84,7 +97,7 @@ class LocalDateTimeSerializationTest { fun testDefaultSerializers() { // should be the same as the ISO 8601 assertKSerializerName("kotlinx.datetime.LocalDateTime", Json.serializersModule.serializer()) - iso8601Serialization(Json.serializersModule.serializer()) + defaultSerialization(Json.serializersModule.serializer()) } object PythonDateTimeSerializer : FormattedLocalDateTimeSerializer("PythonDateTime", LocalDateTime.Format { diff --git a/serialization/common/test/LocalTimeSerializationTest.kt b/serialization/common/test/LocalTimeSerializationTest.kt index f1af3b276..3bd6e09c4 100644 --- a/serialization/common/test/LocalTimeSerializationTest.kt +++ b/serialization/common/test/LocalTimeSerializationTest.kt @@ -15,6 +15,19 @@ import kotlin.test.* class LocalTimeSerializationTest { private fun iso8601Serialization(serializer: KSerializer) { + for ((localTime, json) in listOf( + Pair(LocalTime(2, 1), "\"02:01:00\""), + Pair(LocalTime(23, 59, 1), "\"23:59:01\""), + Pair(LocalTime(23, 59, 59, 990000000), "\"23:59:59.99\""), + Pair(LocalTime(23, 59, 59, 999990000), "\"23:59:59.99999\""), + Pair(LocalTime(23, 59, 59, 999999990), "\"23:59:59.99999999\""), + )) { + assertEquals(json, Json.encodeToString(serializer, localTime)) + assertEquals(localTime, Json.decodeFromString(serializer, json)) + } + } + + private fun defaultSerialization(serializer: KSerializer) { for ((localTime, json) in listOf( Pair(LocalTime(2, 1), "\"02:01\""), Pair(LocalTime(23, 59, 1), "\"23:59:01\""), @@ -72,9 +85,8 @@ class LocalTimeSerializationTest { @Test fun testDefaultSerializers() { - // should be the same as the ISO 8601 assertKSerializerName("kotlinx.datetime.LocalTime", Json.serializersModule.serializer()) - iso8601Serialization(Json.serializersModule.serializer()) + defaultSerialization(Json.serializersModule.serializer()) } object FixedWidthTimeSerializer : FormattedLocalTimeSerializer("FixedWidth", LocalTime.Format { diff --git a/serialization/common/test/UtcOffsetSerializationTest.kt b/serialization/common/test/UtcOffsetSerializationTest.kt index 687c62b9a..32304f13c 100644 --- a/serialization/common/test/UtcOffsetSerializationTest.kt +++ b/serialization/common/test/UtcOffsetSerializationTest.kt @@ -14,28 +14,50 @@ import kotlin.test.* class UtcOffsetSerializationTest { - private fun testSerializationAsPrimitive(serializer: KSerializer) { - val offset2h = UtcOffset(hours = 2) - assertEquals("\"+02:00\"", Json.encodeToString(serializer, offset2h)) - assertEquals(offset2h, Json.decodeFromString(serializer, "\"+02:00\"")) - assertEquals(offset2h, Json.decodeFromString(serializer, "\"+02:00:00\"")) - - assertFailsWith { - Json.decodeFromString(serializer, "\"UTC+02:00\"") // not an offset + private fun iso8601Serialization(serializer: KSerializer) { + // the default form is obtainable and parsable + for ((offset, json) in listOf( + Pair(UtcOffset(hours = 0), "\"Z\""), + Pair(UtcOffset(hours = 1), "\"+01:00\""), + Pair(UtcOffset(hours = 1, minutes = 30), "\"+01:30\""), + Pair(UtcOffset(hours = 1, minutes = 30, seconds = 59), "\"+01:30:59\""), + )) { + assertEquals(json, Json.encodeToString(serializer, offset)) + assertEquals(offset, Json.decodeFromString(serializer, json)) + } + // alternative forms are also parsable + for ((offset, json) in listOf( + Pair(UtcOffset(hours = 0), "\"+00:00\""), + Pair(UtcOffset(hours = 0), "\"z\""), + )) { + assertEquals(offset, Json.decodeFromString(serializer, json)) + } + // some strings aren't parsable + for (json in listOf( + "\"+3\"", + "\"+03\"", + "\"+03:0\"", + "\"UTC+02:00\"", + )) { + assertFailsWith { + Json.decodeFromString(serializer, json) + } } } @Test - fun defaultSerializer() { - assertKSerializerName("kotlinx.datetime.UtcOffset", Json.serializersModule.serializer()) - testSerializationAsPrimitive(Json.serializersModule.serializer()) + fun testIso8601Serialization() { + assertKSerializerName("kotlinx.datetime.UtcOffset", UtcOffsetIso8601Serializer) + iso8601Serialization(UtcOffsetIso8601Serializer) } @Test - fun stringPrimitiveSerializer() { - assertKSerializerName("kotlinx.datetime.UtcOffset", UtcOffsetSerializer) - testSerializationAsPrimitive(UtcOffsetSerializer) - testSerializationAsPrimitive(UtcOffset.serializer()) + fun testDefaultSerializers() { + // should be the same as the ISO 8601 + assertKSerializerName("kotlinx.datetime.UtcOffset", Json.serializersModule.serializer()) + iso8601Serialization(Json.serializersModule.serializer()) + assertKSerializerName("kotlinx.datetime.UtcOffset", UtcOffset.serializer()) + iso8601Serialization(UtcOffset.serializer()) } object FourDigitOffsetSerializer : FormattedUtcOffsetSerializer("FOUR_DIGITS", UtcOffset.Formats.FOUR_DIGITS) From bd555866a8092a5d28949c5d3bb0140a97eb0dad Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Thu, 25 Jul 2024 15:40:08 +0200 Subject: [PATCH 6/7] Ensure different serial names for incompatible serializers Fixes #416 --- core/common/src/DateTimePeriod.kt | 9 ++++++--- .../serializers/DateTimePeriodSerializers.kt | 20 +++++++++++++++---- .../src/serializers/InstantSerializers.kt | 4 ++-- .../src/serializers/LocalDateSerializers.kt | 4 ++-- .../serializers/LocalDateTimeSerializers.kt | 4 ++-- .../src/serializers/LocalTimeSerializers.kt | 4 ++-- .../src/serializers/TimeZoneSerializers.kt | 2 +- .../test/DateTimePeriodSerializationTest.kt | 8 ++++---- .../common/test/InstantSerializationTest.kt | 4 ++-- .../common/test/LocalDateSerializationTest.kt | 4 ++-- .../test/LocalDateTimeSerializationTest.kt | 6 ++++-- .../common/test/LocalTimeSerializationTest.kt | 4 ++-- .../common/test/UtcOffsetSerializationTest.kt | 2 +- 13 files changed, 46 insertions(+), 29 deletions(-) diff --git a/core/common/src/DateTimePeriod.kt b/core/common/src/DateTimePeriod.kt index b35908cdc..c631fbf43 100644 --- a/core/common/src/DateTimePeriod.kt +++ b/core/common/src/DateTimePeriod.kt @@ -9,7 +9,9 @@ import kotlinx.datetime.internal.* import kotlinx.datetime.serializers.DatePeriodIso8601Serializer import kotlinx.datetime.serializers.DateTimePeriodIso8601Serializer import kotlinx.datetime.serializers.DatePeriodComponentSerializer +import kotlinx.datetime.serializers.DatePeriodSerializer import kotlinx.datetime.serializers.DateTimePeriodComponentSerializer +import kotlinx.datetime.serializers.DateTimePeriodSerializer import kotlin.math.* import kotlin.time.Duration import kotlinx.serialization.Serializable @@ -63,13 +65,14 @@ import kotlinx.serialization.Serializable * `DateTimePeriod` can also be returned as the result of instant arithmetic operations (see [Instant.periodUntil]). * * Additionally, there are several `kotlinx-serialization` serializers for [DateTimePeriod]: - * - [DateTimePeriodIso8601Serializer] for the ISO 8601 format; + * - The default serializer, delegating to [toString] and [parse]. + * - [DateTimePeriodIso8601Serializer] for the ISO 8601 format. * - [DateTimePeriodComponentSerializer] for an object with components. * * @sample kotlinx.datetime.test.samples.DateTimePeriodSamples.construction * @sample kotlinx.datetime.test.samples.DateTimePeriodSamples.simpleParsingAndFormatting */ -@Serializable(with = DateTimePeriodIso8601Serializer::class) +@Serializable(with = DateTimePeriodSerializer::class) // TODO: could be error-prone without explicitly named params public sealed class DateTimePeriod { internal abstract val totalMonths: Long @@ -430,7 +433,7 @@ public fun String.toDateTimePeriod(): DateTimePeriod = DateTimePeriod.parse(this * * @sample kotlinx.datetime.test.samples.DatePeriodSamples.simpleParsingAndFormatting */ -@Serializable(with = DatePeriodIso8601Serializer::class) +@Serializable(with = DatePeriodSerializer::class) public class DatePeriod internal constructor( internal override val totalMonths: Long, override val days: Int, diff --git a/core/common/src/serializers/DateTimePeriodSerializers.kt b/core/common/src/serializers/DateTimePeriodSerializers.kt index e5d904fc3..ac76db345 100644 --- a/core/common/src/serializers/DateTimePeriodSerializers.kt +++ b/core/common/src/serializers/DateTimePeriodSerializers.kt @@ -19,7 +19,7 @@ import kotlinx.serialization.encoding.* public object DateTimePeriodComponentSerializer: KSerializer { override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.DateTimePeriod") { + buildClassSerialDescriptor("kotlinx.datetime.DateTimePeriod components") { element("years", isOptional = true) element("months", isOptional = true) element("days", isOptional = true) @@ -81,7 +81,7 @@ public object DateTimePeriodComponentSerializer: KSerializer { public object DateTimePeriodIso8601Serializer: KSerializer { override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("kotlinx.datetime.DateTimePeriod", PrimitiveKind.STRING) + PrimitiveSerialDescriptor("kotlinx.datetime.DateTimePeriod ISO", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): DateTimePeriod = DateTimePeriod.parse(decoder.decodeString()) @@ -110,7 +110,7 @@ public object DatePeriodComponentSerializer: KSerializer { private fun unexpectedNonzero(fieldName: String, value: Int) = unexpectedNonzero(fieldName, value.toLong()) override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.DatePeriod") { + buildClassSerialDescriptor("kotlinx.datetime.DatePeriod components") { element("years", isOptional = true) element("months", isOptional = true) element("days", isOptional = true) @@ -166,7 +166,7 @@ public object DatePeriodComponentSerializer: KSerializer { public object DatePeriodIso8601Serializer: KSerializer { override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("kotlinx.datetime.DatePeriod", PrimitiveKind.STRING) + PrimitiveSerialDescriptor("kotlinx.datetime.DatePeriod ISO", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): DatePeriod = when (val period = DateTimePeriod.parse(decoder.decodeString())) { @@ -179,3 +179,15 @@ public object DatePeriodIso8601Serializer: KSerializer { } } + +@PublishedApi +internal object DateTimePeriodSerializer: KSerializer by DateTimePeriodIso8601Serializer { + override val descriptor = + PrimitiveSerialDescriptor("kotlinx.datetime.DateTimePeriod", PrimitiveKind.STRING) +} + +@PublishedApi +internal object DatePeriodSerializer: KSerializer by DatePeriodIso8601Serializer { + override val descriptor = + PrimitiveSerialDescriptor("kotlinx.datetime.DatePeriod", PrimitiveKind.STRING) +} diff --git a/core/common/src/serializers/InstantSerializers.kt b/core/common/src/serializers/InstantSerializers.kt index e46a0c449..1b3ccdd98 100644 --- a/core/common/src/serializers/InstantSerializers.kt +++ b/core/common/src/serializers/InstantSerializers.kt @@ -22,7 +22,7 @@ import kotlinx.serialization.encoding.* public object InstantIso8601Serializer : KSerializer { override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("kotlinx.datetime.Instant", PrimitiveKind.STRING) + PrimitiveSerialDescriptor("kotlinx.datetime.Instant ISO", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): Instant = Instant.parse(decoder.decodeString(), DateTimeComponents.Formats.ISO_DATE_TIME_OFFSET) @@ -41,7 +41,7 @@ public object InstantIso8601Serializer : KSerializer { public object InstantComponentSerializer : KSerializer { override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.Instant") { + buildClassSerialDescriptor("kotlinx.datetime.Instant components") { element("epochSeconds") element("nanosecondsOfSecond", isOptional = true) } diff --git a/core/common/src/serializers/LocalDateSerializers.kt b/core/common/src/serializers/LocalDateSerializers.kt index 83ff40226..ed0589995 100644 --- a/core/common/src/serializers/LocalDateSerializers.kt +++ b/core/common/src/serializers/LocalDateSerializers.kt @@ -19,7 +19,7 @@ import kotlinx.serialization.encoding.* * @see LocalDate.Formats.ISO */ public object LocalDateIso8601Serializer : KSerializer -by LocalDate.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDate") +by LocalDate.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDate ISO") /** * A serializer for [LocalDate] that represents a value as its components. @@ -29,7 +29,7 @@ by LocalDate.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDate") public object LocalDateComponentSerializer: KSerializer { override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.LocalDate") { + buildClassSerialDescriptor("kotlinx.datetime.LocalDate components") { element("year") element("month") element("day") diff --git a/core/common/src/serializers/LocalDateTimeSerializers.kt b/core/common/src/serializers/LocalDateTimeSerializers.kt index cb0f89bd8..e324b3d06 100644 --- a/core/common/src/serializers/LocalDateTimeSerializers.kt +++ b/core/common/src/serializers/LocalDateTimeSerializers.kt @@ -19,7 +19,7 @@ import kotlinx.serialization.encoding.* * @see LocalDateTime.Formats.ISO */ public object LocalDateTimeIso8601Serializer : KSerializer -by LocalDateTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDateTime") +by LocalDateTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDateTime ISO") /** * A serializer for [LocalDateTime] that represents a value as its components. @@ -29,7 +29,7 @@ by LocalDateTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalDateTime") public object LocalDateTimeComponentSerializer: KSerializer { override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.LocalDateTime") { + buildClassSerialDescriptor("kotlinx.datetime.LocalDateTime components") { element("year") element("month") element("day") diff --git a/core/common/src/serializers/LocalTimeSerializers.kt b/core/common/src/serializers/LocalTimeSerializers.kt index 0b86050b3..d67a63503 100644 --- a/core/common/src/serializers/LocalTimeSerializers.kt +++ b/core/common/src/serializers/LocalTimeSerializers.kt @@ -19,7 +19,7 @@ import kotlinx.serialization.encoding.* * @see LocalTime.Formats.ISO */ public object LocalTimeIso8601Serializer : KSerializer -by LocalTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalTime") +by LocalTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalTime ISO") /** * A serializer for [LocalTime] that represents a value as its components. @@ -29,7 +29,7 @@ by LocalTime.Formats.ISO.asKSerializer("kotlinx.datetime.LocalTime") public object LocalTimeComponentSerializer : KSerializer { override val descriptor: SerialDescriptor = - buildClassSerialDescriptor("kotlinx.datetime.LocalTime") { + buildClassSerialDescriptor("kotlinx.datetime.LocalTime components") { element("hour") element("minute") element("second", isOptional = true) diff --git a/core/common/src/serializers/TimeZoneSerializers.kt b/core/common/src/serializers/TimeZoneSerializers.kt index f9281809a..538aee5b5 100644 --- a/core/common/src/serializers/TimeZoneSerializers.kt +++ b/core/common/src/serializers/TimeZoneSerializers.kt @@ -60,7 +60,7 @@ public object FixedOffsetTimeZoneSerializer: KSerializer { * @see UtcOffset.Formats.ISO */ public object UtcOffsetIso8601Serializer : KSerializer -by UtcOffset.Formats.ISO.asKSerializer("kotlinx.datetime.UtcOffset") +by UtcOffset.Formats.ISO.asKSerializer("kotlinx.datetime.UtcOffset ISO") /** * A serializer for [UtcOffset] that uses the default [UtcOffset.toString]/[UtcOffset.parse]. diff --git a/serialization/common/test/DateTimePeriodSerializationTest.kt b/serialization/common/test/DateTimePeriodSerializationTest.kt index ddb2f606d..9869d4244 100644 --- a/serialization/common/test/DateTimePeriodSerializationTest.kt +++ b/serialization/common/test/DateTimePeriodSerializationTest.kt @@ -97,25 +97,25 @@ class DateTimePeriodSerializationTest { @Test fun testDatePeriodIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.DatePeriod", DatePeriodIso8601Serializer) + assertKSerializerName("kotlinx.datetime.DatePeriod ISO", DatePeriodIso8601Serializer) datePeriodIso8601Serialization(DatePeriodIso8601Serializer, DateTimePeriodIso8601Serializer) } @Test fun testDatePeriodComponentSerialization() { - assertKSerializerName("kotlinx.datetime.DatePeriod", DatePeriodComponentSerializer) + assertKSerializerName("kotlinx.datetime.DatePeriod components", DatePeriodComponentSerializer) datePeriodComponentSerialization(DatePeriodComponentSerializer, DateTimePeriodComponentSerializer) } @Test fun testDateTimePeriodIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.DateTimePeriod", DateTimePeriodIso8601Serializer) + assertKSerializerName("kotlinx.datetime.DateTimePeriod ISO", DateTimePeriodIso8601Serializer) dateTimePeriodIso8601Serialization(DateTimePeriodIso8601Serializer) } @Test fun testDateTimePeriodComponentSerialization() { - assertKSerializerName("kotlinx.datetime.DateTimePeriod", DateTimePeriodComponentSerializer) + assertKSerializerName("kotlinx.datetime.DateTimePeriod components", DateTimePeriodComponentSerializer) dateTimePeriodComponentSerialization(DateTimePeriodComponentSerializer) } diff --git a/serialization/common/test/InstantSerializationTest.kt b/serialization/common/test/InstantSerializationTest.kt index 6d83dc0b1..d7a18a2b4 100644 --- a/serialization/common/test/InstantSerializationTest.kt +++ b/serialization/common/test/InstantSerializationTest.kt @@ -70,13 +70,13 @@ class InstantSerializationTest { @Test fun testIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.Instant", InstantIso8601Serializer) + assertKSerializerName("kotlinx.datetime.Instant ISO", InstantIso8601Serializer) iso8601Serialization(InstantIso8601Serializer) } @Test fun testComponentSerialization() { - assertKSerializerName("kotlinx.datetime.Instant", InstantComponentSerializer) + assertKSerializerName("kotlinx.datetime.Instant components", InstantComponentSerializer) componentSerialization(InstantComponentSerializer) } diff --git a/serialization/common/test/LocalDateSerializationTest.kt b/serialization/common/test/LocalDateSerializationTest.kt index bd6dd9517..420c4db43 100644 --- a/serialization/common/test/LocalDateSerializationTest.kt +++ b/serialization/common/test/LocalDateSerializationTest.kt @@ -56,13 +56,13 @@ class LocalDateSerializationTest { @Test fun testIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.LocalDate", LocalDateIso8601Serializer) + assertKSerializerName("kotlinx.datetime.LocalDate ISO", LocalDateIso8601Serializer) iso8601Serialization(LocalDateIso8601Serializer) } @Test fun testComponentSerialization() { - assertKSerializerName("kotlinx.datetime.LocalDate", LocalDateComponentSerializer) + assertKSerializerName("kotlinx.datetime.LocalDate components", LocalDateComponentSerializer) componentSerialization(LocalDateComponentSerializer) } diff --git a/serialization/common/test/LocalDateTimeSerializationTest.kt b/serialization/common/test/LocalDateTimeSerializationTest.kt index 63649a341..aede7abb2 100644 --- a/serialization/common/test/LocalDateTimeSerializationTest.kt +++ b/serialization/common/test/LocalDateTimeSerializationTest.kt @@ -83,13 +83,15 @@ class LocalDateTimeSerializationTest { @Test fun testIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.LocalDateTime", LocalDateTimeComponentSerializer) + assertKSerializerName("kotlinx.datetime.LocalDateTime ISO", LocalDateTimeIso8601Serializer) iso8601Serialization(LocalDateTimeIso8601Serializer) } @Test fun testComponentSerialization() { - assertKSerializerName("kotlinx.datetime.LocalDateTime", LocalDateTimeComponentSerializer) + assertKSerializerName( + "kotlinx.datetime.LocalDateTime components", LocalDateTimeComponentSerializer + ) componentSerialization(LocalDateTimeComponentSerializer) } diff --git a/serialization/common/test/LocalTimeSerializationTest.kt b/serialization/common/test/LocalTimeSerializationTest.kt index 3bd6e09c4..c7d44b40a 100644 --- a/serialization/common/test/LocalTimeSerializationTest.kt +++ b/serialization/common/test/LocalTimeSerializationTest.kt @@ -73,13 +73,13 @@ class LocalTimeSerializationTest { @Test fun testIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.LocalTime", LocalTimeIso8601Serializer) + assertKSerializerName("kotlinx.datetime.LocalTime ISO", LocalTimeIso8601Serializer) iso8601Serialization(LocalTimeIso8601Serializer) } @Test fun testComponentSerialization() { - assertKSerializerName("kotlinx.datetime.LocalTime", LocalTimeComponentSerializer) + assertKSerializerName("kotlinx.datetime.LocalTime components", LocalTimeComponentSerializer) componentSerialization(LocalTimeComponentSerializer) } diff --git a/serialization/common/test/UtcOffsetSerializationTest.kt b/serialization/common/test/UtcOffsetSerializationTest.kt index 32304f13c..b4ac04776 100644 --- a/serialization/common/test/UtcOffsetSerializationTest.kt +++ b/serialization/common/test/UtcOffsetSerializationTest.kt @@ -47,7 +47,7 @@ class UtcOffsetSerializationTest { @Test fun testIso8601Serialization() { - assertKSerializerName("kotlinx.datetime.UtcOffset", UtcOffsetIso8601Serializer) + assertKSerializerName("kotlinx.datetime.UtcOffset ISO", UtcOffsetIso8601Serializer) iso8601Serialization(UtcOffsetIso8601Serializer) } From 05f7e25977f1a832fe1eacf00026e396a8dbb3b9 Mon Sep 17 00:00:00 2001 From: Dmitry Khalanskiy Date: Mon, 17 Mar 2025 14:33:45 +0100 Subject: [PATCH 7/7] Add the API dump --- core/api/kotlinx-datetime.api | 109 +++++++++++++++++++++++++++++ core/api/kotlinx-datetime.klib.api | 107 ++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+) diff --git a/core/api/kotlinx-datetime.api b/core/api/kotlinx-datetime.api index dc61840a7..e93d6cc10 100644 --- a/core/api/kotlinx-datetime.api +++ b/core/api/kotlinx-datetime.api @@ -796,6 +796,15 @@ public final class kotlinx/datetime/serializers/DatePeriodIso8601Serializer : ko public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/DatePeriod;)V } +public final class kotlinx/datetime/serializers/DatePeriodSerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lkotlinx/datetime/serializers/DatePeriodSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/DatePeriod; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/DatePeriod;)V +} + public final class kotlinx/datetime/serializers/DateTimePeriodComponentSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lkotlinx/datetime/serializers/DateTimePeriodComponentSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; @@ -814,6 +823,15 @@ public final class kotlinx/datetime/serializers/DateTimePeriodIso8601Serializer public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/DateTimePeriod;)V } +public final class kotlinx/datetime/serializers/DateTimePeriodSerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lkotlinx/datetime/serializers/DateTimePeriodSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/DateTimePeriod; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/DateTimePeriod;)V +} + public final class kotlinx/datetime/serializers/DateTimeUnitSerializer : kotlinx/serialization/internal/AbstractPolymorphicSerializer { public static final field INSTANCE Lkotlinx/datetime/serializers/DateTimeUnitSerializer; public fun findPolymorphicSerializerOrNull (Lkotlinx/serialization/encoding/CompositeDecoder;Ljava/lang/String;)Lkotlinx/serialization/DeserializationStrategy; @@ -850,6 +868,52 @@ public final class kotlinx/datetime/serializers/FixedOffsetTimeZoneSerializer : public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/FixedOffsetTimeZone;)V } +public abstract class kotlinx/datetime/serializers/FormattedInstantSerializer : kotlinx/serialization/KSerializer { + public fun (Ljava/lang/String;Lkotlinx/datetime/format/DateTimeFormat;)V + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/Instant; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/Instant;)V + public fun toString ()Ljava/lang/String; +} + +public abstract class kotlinx/datetime/serializers/FormattedLocalDateSerializer : kotlinx/serialization/KSerializer { + public fun (Ljava/lang/String;Lkotlinx/datetime/format/DateTimeFormat;)V + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/LocalDate; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/LocalDate;)V +} + +public abstract class kotlinx/datetime/serializers/FormattedLocalDateTimeSerializer : kotlinx/serialization/KSerializer { + public fun (Ljava/lang/String;Lkotlinx/datetime/format/DateTimeFormat;)V + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/LocalDateTime; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/LocalDateTime;)V +} + +public abstract class kotlinx/datetime/serializers/FormattedLocalTimeSerializer : kotlinx/serialization/KSerializer { + public fun (Ljava/lang/String;Lkotlinx/datetime/format/DateTimeFormat;)V + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/LocalTime; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/LocalTime;)V +} + +public abstract class kotlinx/datetime/serializers/FormattedUtcOffsetSerializer : kotlinx/serialization/KSerializer { + public fun (Ljava/lang/String;Lkotlinx/datetime/format/DateTimeFormat;)V + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/UtcOffset; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/UtcOffset;)V +} + public final class kotlinx/datetime/serializers/InstantComponentSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lkotlinx/datetime/serializers/InstantComponentSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; @@ -868,6 +932,15 @@ public final class kotlinx/datetime/serializers/InstantIso8601Serializer : kotli public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/Instant;)V } +public final class kotlinx/datetime/serializers/InstantSerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lkotlinx/datetime/serializers/InstantSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/Instant; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/Instant;)V +} + public final class kotlinx/datetime/serializers/LocalDateComponentSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lkotlinx/datetime/serializers/LocalDateComponentSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; @@ -886,6 +959,15 @@ public final class kotlinx/datetime/serializers/LocalDateIso8601Serializer : kot public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/LocalDate;)V } +public final class kotlinx/datetime/serializers/LocalDateSerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lkotlinx/datetime/serializers/LocalDateSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/LocalDate; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/LocalDate;)V +} + public final class kotlinx/datetime/serializers/LocalDateTimeComponentSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lkotlinx/datetime/serializers/LocalDateTimeComponentSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; @@ -904,6 +986,15 @@ public final class kotlinx/datetime/serializers/LocalDateTimeIso8601Serializer : public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/LocalDateTime;)V } +public final class kotlinx/datetime/serializers/LocalDateTimeSerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lkotlinx/datetime/serializers/LocalDateTimeSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/LocalDateTime; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/LocalDateTime;)V +} + public final class kotlinx/datetime/serializers/LocalTimeComponentSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lkotlinx/datetime/serializers/LocalTimeComponentSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; @@ -922,6 +1013,15 @@ public final class kotlinx/datetime/serializers/LocalTimeIso8601Serializer : kot public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/LocalTime;)V } +public final class kotlinx/datetime/serializers/LocalTimeSerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lkotlinx/datetime/serializers/LocalTimeSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/LocalTime; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/LocalTime;)V +} + public final class kotlinx/datetime/serializers/MonthBasedDateTimeUnitSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lkotlinx/datetime/serializers/MonthBasedDateTimeUnitSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; @@ -958,6 +1058,15 @@ public final class kotlinx/datetime/serializers/TimeZoneSerializer : kotlinx/ser public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/TimeZone;)V } +public final class kotlinx/datetime/serializers/UtcOffsetIso8601Serializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lkotlinx/datetime/serializers/UtcOffsetIso8601Serializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lkotlinx/datetime/UtcOffset; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lkotlinx/datetime/UtcOffset;)V +} + public final class kotlinx/datetime/serializers/UtcOffsetSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lkotlinx/datetime/serializers/UtcOffsetSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; diff --git a/core/api/kotlinx-datetime.klib.api b/core/api/kotlinx-datetime.klib.api index 808f0fa30..ed2c83efe 100644 --- a/core/api/kotlinx-datetime.klib.api +++ b/core/api/kotlinx-datetime.klib.api @@ -135,6 +135,57 @@ sealed interface kotlinx.datetime.format/DateTimeFormatBuilder { // kotlinx.date } } +abstract class kotlinx.datetime.serializers/FormattedInstantSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/FormattedInstantSerializer|null[0] + constructor (kotlin/String, kotlinx.datetime.format/DateTimeFormat) // kotlinx.datetime.serializers/FormattedInstantSerializer.|(kotlin.String;kotlinx.datetime.format.DateTimeFormat){}[0] + + open val descriptor // kotlinx.datetime.serializers/FormattedInstantSerializer.descriptor|{}descriptor[0] + open fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/FormattedInstantSerializer.descriptor.|(){}[0] + + open fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/Instant // kotlinx.datetime.serializers/FormattedInstantSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + open fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/Instant) // kotlinx.datetime.serializers/FormattedInstantSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.Instant){}[0] + open fun toString(): kotlin/String // kotlinx.datetime.serializers/FormattedInstantSerializer.toString|toString(){}[0] +} + +abstract class kotlinx.datetime.serializers/FormattedLocalDateSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/FormattedLocalDateSerializer|null[0] + constructor (kotlin/String, kotlinx.datetime.format/DateTimeFormat) // kotlinx.datetime.serializers/FormattedLocalDateSerializer.|(kotlin.String;kotlinx.datetime.format.DateTimeFormat){}[0] + + open val descriptor // kotlinx.datetime.serializers/FormattedLocalDateSerializer.descriptor|{}descriptor[0] + open fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/FormattedLocalDateSerializer.descriptor.|(){}[0] + + open fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/LocalDate // kotlinx.datetime.serializers/FormattedLocalDateSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + open fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/LocalDate) // kotlinx.datetime.serializers/FormattedLocalDateSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.LocalDate){}[0] +} + +abstract class kotlinx.datetime.serializers/FormattedLocalDateTimeSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/FormattedLocalDateTimeSerializer|null[0] + constructor (kotlin/String, kotlinx.datetime.format/DateTimeFormat) // kotlinx.datetime.serializers/FormattedLocalDateTimeSerializer.|(kotlin.String;kotlinx.datetime.format.DateTimeFormat){}[0] + + open val descriptor // kotlinx.datetime.serializers/FormattedLocalDateTimeSerializer.descriptor|{}descriptor[0] + open fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/FormattedLocalDateTimeSerializer.descriptor.|(){}[0] + + open fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/LocalDateTime // kotlinx.datetime.serializers/FormattedLocalDateTimeSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + open fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/LocalDateTime) // kotlinx.datetime.serializers/FormattedLocalDateTimeSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.LocalDateTime){}[0] +} + +abstract class kotlinx.datetime.serializers/FormattedLocalTimeSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/FormattedLocalTimeSerializer|null[0] + constructor (kotlin/String, kotlinx.datetime.format/DateTimeFormat) // kotlinx.datetime.serializers/FormattedLocalTimeSerializer.|(kotlin.String;kotlinx.datetime.format.DateTimeFormat){}[0] + + open val descriptor // kotlinx.datetime.serializers/FormattedLocalTimeSerializer.descriptor|{}descriptor[0] + open fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/FormattedLocalTimeSerializer.descriptor.|(){}[0] + + open fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/LocalTime // kotlinx.datetime.serializers/FormattedLocalTimeSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + open fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/LocalTime) // kotlinx.datetime.serializers/FormattedLocalTimeSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.LocalTime){}[0] +} + +abstract class kotlinx.datetime.serializers/FormattedUtcOffsetSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/FormattedUtcOffsetSerializer|null[0] + constructor (kotlin/String, kotlinx.datetime.format/DateTimeFormat) // kotlinx.datetime.serializers/FormattedUtcOffsetSerializer.|(kotlin.String;kotlinx.datetime.format.DateTimeFormat){}[0] + + open val descriptor // kotlinx.datetime.serializers/FormattedUtcOffsetSerializer.descriptor|{}descriptor[0] + open fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/FormattedUtcOffsetSerializer.descriptor.|(){}[0] + + open fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/UtcOffset // kotlinx.datetime.serializers/FormattedUtcOffsetSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + open fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/UtcOffset) // kotlinx.datetime.serializers/FormattedUtcOffsetSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.UtcOffset){}[0] +} + final class kotlinx.datetime.format/DateTimeComponents { // kotlinx.datetime.format/DateTimeComponents|null[0] final var amPm // kotlinx.datetime.format/DateTimeComponents.amPm|{}amPm[0] final fun (): kotlinx.datetime.format/AmPmMarker? // kotlinx.datetime.format/DateTimeComponents.amPm.|(){}[0] @@ -654,6 +705,14 @@ final object kotlinx.datetime.serializers/DatePeriodIso8601Serializer : kotlinx. final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/DatePeriod) // kotlinx.datetime.serializers/DatePeriodIso8601Serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.DatePeriod){}[0] } +final object kotlinx.datetime.serializers/DatePeriodSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/DatePeriodSerializer|null[0] + final val descriptor // kotlinx.datetime.serializers/DatePeriodSerializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/DatePeriodSerializer.descriptor.|(){}[0] + + final fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/DatePeriod // kotlinx.datetime.serializers/DatePeriodSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/DatePeriod) // kotlinx.datetime.serializers/DatePeriodSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.DatePeriod){}[0] +} + final object kotlinx.datetime.serializers/DateTimePeriodComponentSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/DateTimePeriodComponentSerializer|null[0] final val descriptor // kotlinx.datetime.serializers/DateTimePeriodComponentSerializer.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/DateTimePeriodComponentSerializer.descriptor.|(){}[0] @@ -670,6 +729,14 @@ final object kotlinx.datetime.serializers/DateTimePeriodIso8601Serializer : kotl final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/DateTimePeriod) // kotlinx.datetime.serializers/DateTimePeriodIso8601Serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.DateTimePeriod){}[0] } +final object kotlinx.datetime.serializers/DateTimePeriodSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/DateTimePeriodSerializer|null[0] + final val descriptor // kotlinx.datetime.serializers/DateTimePeriodSerializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/DateTimePeriodSerializer.descriptor.|(){}[0] + + final fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/DateTimePeriod // kotlinx.datetime.serializers/DateTimePeriodSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/DateTimePeriod) // kotlinx.datetime.serializers/DateTimePeriodSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.DateTimePeriod){}[0] +} + final object kotlinx.datetime.serializers/DateTimeUnitSerializer : kotlinx.serialization.internal/AbstractPolymorphicSerializer { // kotlinx.datetime.serializers/DateTimeUnitSerializer|null[0] final val baseClass // kotlinx.datetime.serializers/DateTimeUnitSerializer.baseClass|{}baseClass[0] final fun (): kotlin.reflect/KClass // kotlinx.datetime.serializers/DateTimeUnitSerializer.baseClass.|(){}[0] @@ -720,6 +787,14 @@ final object kotlinx.datetime.serializers/InstantIso8601Serializer : kotlinx.ser final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/Instant) // kotlinx.datetime.serializers/InstantIso8601Serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.Instant){}[0] } +final object kotlinx.datetime.serializers/InstantSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/InstantSerializer|null[0] + final val descriptor // kotlinx.datetime.serializers/InstantSerializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/InstantSerializer.descriptor.|(){}[0] + + final fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/Instant // kotlinx.datetime.serializers/InstantSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/Instant) // kotlinx.datetime.serializers/InstantSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.Instant){}[0] +} + final object kotlinx.datetime.serializers/LocalDateComponentSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/LocalDateComponentSerializer|null[0] final val descriptor // kotlinx.datetime.serializers/LocalDateComponentSerializer.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/LocalDateComponentSerializer.descriptor.|(){}[0] @@ -736,6 +811,14 @@ final object kotlinx.datetime.serializers/LocalDateIso8601Serializer : kotlinx.s final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/LocalDate) // kotlinx.datetime.serializers/LocalDateIso8601Serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.LocalDate){}[0] } +final object kotlinx.datetime.serializers/LocalDateSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/LocalDateSerializer|null[0] + final val descriptor // kotlinx.datetime.serializers/LocalDateSerializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/LocalDateSerializer.descriptor.|(){}[0] + + final fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/LocalDate // kotlinx.datetime.serializers/LocalDateSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/LocalDate) // kotlinx.datetime.serializers/LocalDateSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.LocalDate){}[0] +} + final object kotlinx.datetime.serializers/LocalDateTimeComponentSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/LocalDateTimeComponentSerializer|null[0] final val descriptor // kotlinx.datetime.serializers/LocalDateTimeComponentSerializer.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/LocalDateTimeComponentSerializer.descriptor.|(){}[0] @@ -752,6 +835,14 @@ final object kotlinx.datetime.serializers/LocalDateTimeIso8601Serializer : kotli final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/LocalDateTime) // kotlinx.datetime.serializers/LocalDateTimeIso8601Serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.LocalDateTime){}[0] } +final object kotlinx.datetime.serializers/LocalDateTimeSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/LocalDateTimeSerializer|null[0] + final val descriptor // kotlinx.datetime.serializers/LocalDateTimeSerializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/LocalDateTimeSerializer.descriptor.|(){}[0] + + final fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/LocalDateTime // kotlinx.datetime.serializers/LocalDateTimeSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/LocalDateTime) // kotlinx.datetime.serializers/LocalDateTimeSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.LocalDateTime){}[0] +} + final object kotlinx.datetime.serializers/LocalTimeComponentSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/LocalTimeComponentSerializer|null[0] final val descriptor // kotlinx.datetime.serializers/LocalTimeComponentSerializer.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/LocalTimeComponentSerializer.descriptor.|(){}[0] @@ -768,6 +859,14 @@ final object kotlinx.datetime.serializers/LocalTimeIso8601Serializer : kotlinx.s final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/LocalTime) // kotlinx.datetime.serializers/LocalTimeIso8601Serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.LocalTime){}[0] } +final object kotlinx.datetime.serializers/LocalTimeSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/LocalTimeSerializer|null[0] + final val descriptor // kotlinx.datetime.serializers/LocalTimeSerializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/LocalTimeSerializer.descriptor.|(){}[0] + + final fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/LocalTime // kotlinx.datetime.serializers/LocalTimeSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/LocalTime) // kotlinx.datetime.serializers/LocalTimeSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.LocalTime){}[0] +} + final object kotlinx.datetime.serializers/MonthBasedDateTimeUnitSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/MonthBasedDateTimeUnitSerializer|null[0] final val descriptor // kotlinx.datetime.serializers/MonthBasedDateTimeUnitSerializer.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/MonthBasedDateTimeUnitSerializer.descriptor.|(){}[0] @@ -800,6 +899,14 @@ final object kotlinx.datetime.serializers/TimeZoneSerializer : kotlinx.serializa final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/TimeZone) // kotlinx.datetime.serializers/TimeZoneSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.TimeZone){}[0] } +final object kotlinx.datetime.serializers/UtcOffsetIso8601Serializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/UtcOffsetIso8601Serializer|null[0] + final val descriptor // kotlinx.datetime.serializers/UtcOffsetIso8601Serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/UtcOffsetIso8601Serializer.descriptor.|(){}[0] + + final fun deserialize(kotlinx.serialization.encoding/Decoder): kotlinx.datetime/UtcOffset // kotlinx.datetime.serializers/UtcOffsetIso8601Serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, kotlinx.datetime/UtcOffset) // kotlinx.datetime.serializers/UtcOffsetIso8601Serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;kotlinx.datetime.UtcOffset){}[0] +} + final object kotlinx.datetime.serializers/UtcOffsetSerializer : kotlinx.serialization/KSerializer { // kotlinx.datetime.serializers/UtcOffsetSerializer|null[0] final val descriptor // kotlinx.datetime.serializers/UtcOffsetSerializer.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // kotlinx.datetime.serializers/UtcOffsetSerializer.descriptor.|(){}[0]