Skip to content

Commit 4731e15

Browse files
committed
UtcOffset serialization (as a string primitive)
1 parent ebe4253 commit 4731e15

File tree

6 files changed

+68
-1
lines changed

6 files changed

+68
-1
lines changed

core/common/src/UtcOffset.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
package kotlinx.datetime
77

8+
import kotlinx.datetime.serializers.UtcOffsetSerializer
9+
import kotlinx.serialization.Serializable
10+
11+
@Serializable(with = UtcOffsetSerializer::class)
812
public expect class UtcOffset {
913
public val totalSeconds: Int
1014

core/common/src/serializers/TimeZoneSerializers.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package kotlinx.datetime.serializers
77

88
import kotlinx.datetime.FixedOffsetTimeZone
99
import kotlinx.datetime.TimeZone
10+
import kotlinx.datetime.UtcOffset
1011
import kotlinx.serialization.*
1112
import kotlinx.serialization.descriptors.*
1213
import kotlinx.serialization.encoding.*
@@ -25,7 +26,7 @@ public object TimeZoneSerializer: KSerializer<TimeZone> {
2526

2627
public object FixedOffsetTimeZoneSerializer: KSerializer<FixedOffsetTimeZone> {
2728

28-
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ZoneOffset", PrimitiveKind.STRING)
29+
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("FixedOffsetTimeZone", PrimitiveKind.STRING)
2930

3031
override fun deserialize(decoder: Decoder): FixedOffsetTimeZone {
3132
val zone = TimeZone.of(decoder.decodeString())
@@ -41,3 +42,17 @@ public object FixedOffsetTimeZoneSerializer: KSerializer<FixedOffsetTimeZone> {
4142
}
4243

4344
}
45+
46+
public object UtcOffsetSerializer: KSerializer<UtcOffset> {
47+
48+
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UtcOffset", PrimitiveKind.STRING)
49+
50+
override fun deserialize(decoder: Decoder): UtcOffset {
51+
return UtcOffset.parse(decoder.decodeString())
52+
}
53+
54+
override fun serialize(encoder: Encoder, value: UtcOffset) {
55+
encoder.encodeString(value.toString())
56+
}
57+
58+
}

core/js/src/UtcOffset.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
package kotlinx.datetime
77

88
import kotlinx.datetime.internal.JSJoda.ZoneOffset
9+
import kotlinx.datetime.serializers.UtcOffsetSerializer
10+
import kotlinx.serialization.Serializable
911

12+
@Serializable(with = UtcOffsetSerializer::class)
1013
public actual class UtcOffset(internal val zoneOffset: ZoneOffset) {
1114
public actual val totalSeconds: Int get() = zoneOffset.totalSeconds().toInt()
1215

core/jvm/src/UtcOffsetJvm.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55

66
package kotlinx.datetime
77

8+
import kotlinx.datetime.serializers.UtcOffsetSerializer
9+
import kotlinx.serialization.Serializable
810
import java.time.DateTimeException
911
import java.time.ZoneOffset
1012

13+
@Serializable(with = UtcOffsetSerializer::class)
1114
public actual class UtcOffset(internal val zoneOffset: ZoneOffset) {
1215
public actual val totalSeconds: Int get() = zoneOffset.totalSeconds
1316

core/native/src/UtcOffset.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55

66
package kotlinx.datetime
77

8+
import kotlinx.datetime.serializers.UtcOffsetSerializer
9+
import kotlinx.serialization.Serializable
810
import kotlin.math.abs
911
import kotlin.native.concurrent.ThreadLocal
1012

13+
@Serializable(with = UtcOffsetSerializer::class)
1114
public actual class UtcOffset internal constructor(public actual val totalSeconds: Int) {
1215
private val id: String = zoneIdByOffset(totalSeconds)
1316

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2019-2021 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package kotlinx.datetime.serialization.test
7+
8+
import kotlinx.datetime.*
9+
import kotlinx.datetime.serializers.*
10+
import kotlinx.serialization.KSerializer
11+
import kotlinx.serialization.json.*
12+
import kotlinx.serialization.serializer
13+
import kotlin.test.*
14+
15+
class UtcOffsetSerializationTest {
16+
17+
private fun testSerializationAsPrimitive(serializer: KSerializer<UtcOffset>) {
18+
val offset2h = UtcOffset.parse("+2")
19+
assertEquals("\"+02:00\"", Json.encodeToString(serializer, offset2h))
20+
assertEquals(offset2h, Json.decodeFromString(serializer, "\"+02:00\""))
21+
assertEquals(offset2h, Json.decodeFromString(serializer, "\"+02\""))
22+
assertEquals(offset2h, Json.decodeFromString(serializer, "\"+2\""))
23+
24+
assertFailsWith<IllegalArgumentException> {
25+
Json.decodeFromString(serializer, "\"UTC+02:00\"") // not an offset
26+
}
27+
}
28+
29+
@Test
30+
fun defaultSerializer() {
31+
testSerializationAsPrimitive(Json.serializersModule.serializer())
32+
}
33+
34+
@Test
35+
fun stringPrimitiveSerializer() {
36+
testSerializationAsPrimitive(UtcOffsetSerializer)
37+
testSerializationAsPrimitive(UtcOffset.serializer())
38+
}
39+
}

0 commit comments

Comments
 (0)