Skip to content

Commit 3bacb97

Browse files
committed
improve timestamp to milliseconds conversion
1 parent 8c268f6 commit 3bacb97

File tree

2 files changed

+33
-13
lines changed
  • firebase-firestore/src

2 files changed

+33
-13
lines changed

firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
package dev.gitlive.firebase.firestore
22

3+
import dev.gitlive.firebase.FirebaseDecoder
34
import dev.gitlive.firebase.FirebaseEncoder
45
import dev.gitlive.firebase.SpecialValueSerializer
56
import dev.gitlive.firebase.firestore.DoubleAsTimestampSerializer.serverTimestamp
67
import kotlinx.serialization.Serializable
78
import kotlinx.serialization.SerializationException
9+
import kotlin.time.Duration
10+
import kotlin.time.Duration.Companion.milliseconds
11+
import kotlin.time.Duration.Companion.nanoseconds
12+
import kotlin.time.Duration.Companion.seconds
13+
import kotlin.time.DurationUnit
814

915
/** A class representing a platform specific Firebase Timestamp. */
1016
expect class NativeTimestamp
@@ -31,11 +37,16 @@ expect class Timestamp internal constructor(nativeValue: NativeTimestamp): BaseT
3137
object ServerTimestamp: BaseTimestamp
3238
}
3339

34-
fun Timestamp.Companion.fromMilliseconds(milliseconds: Double): Timestamp =
35-
Timestamp((milliseconds / 1000).toLong(), ((milliseconds % 1000) * 1000000).toInt())
36-
fun Timestamp.toMilliseconds(): Double = seconds * 1000 + nanoseconds / 1000000.0
40+
fun Timestamp.Companion.fromDuration(duration: Duration): Timestamp =
41+
duration.toComponents { seconds, nanoseconds ->
42+
Timestamp(seconds, nanoseconds)
43+
}
44+
fun Timestamp.toDuration(): Duration = seconds.seconds + nanoseconds.nanoseconds
45+
46+
fun Timestamp.Companion.fromMilliseconds(milliseconds: Double): Timestamp = fromDuration(milliseconds.milliseconds)
47+
fun Timestamp.toMilliseconds(): Double = toDuration().toDouble(DurationUnit.MILLISECONDS)
3748

38-
/** A serializer for [BaseTimestamp]. If used with [FirebaseEncoder] performs serialization using native Firebase mechanisms. */
49+
/** A serializer for [BaseTimestamp]. Must be used with [FirebaseEncoder]/[FirebaseDecoder]. */
3950
object BaseTimestampSerializer : SpecialValueSerializer<BaseTimestamp>(
4051
serialName = "Timestamp",
4152
toNativeValue = { value ->
@@ -54,7 +65,7 @@ object BaseTimestampSerializer : SpecialValueSerializer<BaseTimestamp>(
5465
}
5566
)
5667

57-
/** A serializer for [Timestamp]. If used with [FirebaseEncoder] performs serialization using native Firebase mechanisms. */
68+
/** A serializer for [Timestamp]. Must be used with [FirebaseEncoder]/[FirebaseDecoder]. */
5869
object TimestampSerializer : SpecialValueSerializer<Timestamp>(
5970
serialName = "Timestamp",
6071
toNativeValue = Timestamp::nativeValue,
@@ -66,7 +77,7 @@ object TimestampSerializer : SpecialValueSerializer<Timestamp>(
6677
}
6778
)
6879

69-
/** A serializer for [Timestamp.ServerTimestamp]. If used with [FirebaseEncoder] performs serialization using native Firebase mechanisms. */
80+
/** A serializer for [Timestamp.ServerTimestamp]. Must be used with [FirebaseEncoder]/[FirebaseDecoder]. */
7081
object ServerTimestampSerializer : SpecialValueSerializer<Timestamp.ServerTimestamp>(
7182
serialName = "Timestamp",
7283
toNativeValue = { FieldValue.serverTimestamp.nativeValue },
@@ -84,7 +95,7 @@ object DoubleAsTimestampSerializer : SpecialValueSerializer<Double>(
8495
toNativeValue = { value ->
8596
when(value) {
8697
serverTimestamp -> FieldValue.serverTimestamp.nativeValue
87-
else -> Timestamp.fromMilliseconds(value)
98+
else -> Timestamp.fromMilliseconds(value).nativeValue
8899
}
89100
},
90101
fromNativeValue = { value ->

firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/TimestampTests.kt

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,23 @@ class TimestampTests {
100100

101101
@Test
102102
fun timestampMillisecondsConversion() = runTest {
103-
val ms = 1666170858063
104-
val seconds = 1666170858
105-
val nanoseconds = 63000000 // 1 millisecond = 1000 microseconds = 1000000 nanoseconds
106-
val timestamp = Timestamp.fromMilliseconds(ms.toDouble())
103+
val duration = 1666170858063.milliseconds
104+
val (seconds, nanoseconds) = ms.toComponents { seconds, nanoseconds -> seconds to nanoseconds }
105+
val ms = duration.toDouble(DurationUnit.MILLISECONDS)
107106

108-
assertEquals(seconds.toLong(), timestamp.seconds)
107+
val timestamp = Timestamp.fromMilliseconds(ms)
108+
assertEquals(seconds, timestamp.seconds)
109109
assertEquals(nanoseconds, timestamp.nanoseconds)
110+
assertEquals(ms, timestamp.toMilliseconds())
111+
}
110112

111-
assertEquals(ms, timestamp.toMilliseconds().toLong())
113+
@Test
114+
fun timestampDurationConversion() = runTest {
115+
val duration = 1666170858063.milliseconds
116+
val (seconds, nanoseconds) = ms.toComponents { seconds, nanoseconds -> seconds to nanoseconds }
117+
val timestamp = Timestamp.fromDuration(ms)
118+
assertEquals(seconds, timestamp.seconds)
119+
assertEquals(nanoseconds, timestamp.nanoseconds)
120+
assertEquals(duration, timestamp.toDuration())
112121
}
113122
}

0 commit comments

Comments
 (0)