-
Notifications
You must be signed in to change notification settings - Fork 2
/
ContextualColumnCustom.kt
71 lines (61 loc) · 3.28 KB
/
ContextualColumnCustom.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package io.exoquery.sql.examples
import io.exoquery.sql.Param
import io.exoquery.sql.Sql
import io.exoquery.sql.jdbc.*
import io.exoquery.sql.jdbc.JdbcTimeEncodingLegacy.JZonedDateTimeEncoder
import io.exoquery.sql.jdbc.JdbcTimeEncodingLegacy.JZonedDateTimeDecoder
import io.zonky.test.db.postgres.embedded.EmbeddedPostgres
import kotlinx.serialization.Contextual
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import java.time.LocalDate
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.TimeZone
object ContextualColumnCustom {
data class MyDateTime(val year: Int, val day: Int, val month: Int, val timeZone: TimeZone) {
override fun toString(): String = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, timeZone.toZoneId()).format(DateTimeFormatter.ISO_ZONED_DATE_TIME)
companion object {
fun fromString(s: String): MyDateTime {
val zdt = ZonedDateTime.from(DateTimeFormatter.ISO_ZONED_DATE_TIME.parse(s))
return MyDateTime(zdt.year, zdt.dayOfMonth, zdt.monthValue, TimeZone.getTimeZone(zdt.zone))
}
fun fromLocalDate(ld: LocalDate): MyDateTime = MyDateTime(ld.year, ld.dayOfMonth, ld.monthValue, TimeZone.getTimeZone("UTC"))
}
}
object MyDateTimeAsStringSerialzier: KSerializer<MyDateTime> {
override val descriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: MyDateTime) = encoder.encodeString(value.toString())
override fun deserialize(decoder: Decoder): MyDateTime = MyDateTime.fromString(decoder.decodeString())
}
@Serializable
data class Customer(val id: Int, val firstName: String, val lastName: String, @Contextual val createdAt: MyDateTime)
suspend fun main() {
val postgres = EmbeddedPostgres.start()
postgres.run("CREATE TABLE customers (id SERIAL PRIMARY KEY, first_name TEXT, last_name TEXT, created_at TIMESTAMP WITH TIME ZONE)")
val ctx =
TerpalDriver.Postgres(
postgres.postgresDatabase,
JdbcEncodingConfig.Default(
setOf(JZonedDateTimeEncoder.contramap { md: MyDateTime -> ZonedDateTime.of(md.year, md.month, md.day, 0, 0, 0, 0, md.timeZone.toZoneId()) }),
setOf(JZonedDateTimeDecoder.map { zd -> MyDateTime(zd.year, zd.dayOfMonth, zd.monthValue, TimeZone.getTimeZone(zd.zone)) })
)
)
ctx.run(Sql("INSERT INTO customers (first_name, last_name, created_at) VALUES (${id("Alice")}, ${id("Smith")}, ${Param.ctx(MyDateTime(2022, 1, 2, TimeZone.getTimeZone(ZoneOffset.UTC)))})").action())
val customers = ctx.run(Sql("SELECT * FROM customers").queryOf<Customer>())
val module = SerializersModule { contextual(MyDateTime::class, MyDateTimeAsStringSerialzier) }
val json = Json { serializersModule = module }
println(json.encodeToString(ListSerializer(Customer.serializer()), customers))
}
}
suspend fun main() {
ContextualColumnCustom.main()
}