From 1f6c68707c696b7a9ee412a18fb399b3416c3863 Mon Sep 17 00:00:00 2001 From: Jan Seeger Date: Sat, 22 Jun 2024 14:21:13 +0200 Subject: [PATCH] Add kotlinx-datetime module (#198) --- gradle/libs.versions.toml | 3 ++ kotlinx-uuid-datetime/README.md | 42 +++++++++++++++++++ kotlinx-uuid-datetime/build.gradle.kts | 36 ++++++++++++++++ .../main/kotlin/kotlinx/uuid/datetime/Dsl.kt | 20 +++++++++ .../kotlinx/uuid/datetime/InstantTest.kt | 27 ++++++++++++ settings.gradle.kts | 1 + 6 files changed, 129 insertions(+) create mode 100644 kotlinx-uuid-datetime/README.md create mode 100644 kotlinx-uuid-datetime/build.gradle.kts create mode 100644 kotlinx-uuid-datetime/src/main/kotlin/kotlinx/uuid/datetime/Dsl.kt create mode 100644 kotlinx-uuid-datetime/src/test/kotlin/kotlinx/uuid/datetime/InstantTest.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1413167..8873056 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,6 +2,7 @@ kotlin = "2.0.0" serialization = "1.7.0" exposed = "0.51.1" +datetime = "0.6.0" [libraries] serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "serialization" } @@ -16,6 +17,8 @@ slf4j = { module = "org.slf4j:slf4j-simple", version = "2.0.13" } sqldelight-runtime = { module = "app.cash.sqldelight:runtime", version = "2.0.2" } +datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" } + [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } diff --git a/kotlinx-uuid-datetime/README.md b/kotlinx-uuid-datetime/README.md new file mode 100644 index 0000000..358f289 --- /dev/null +++ b/kotlinx-uuid-datetime/README.md @@ -0,0 +1,42 @@ +# Module kotlinx-uuid-datetime + +Provides support for UUIDv7 using kotlinx-datetime. + +```kotlin +dependencies { + implementation("app.softwork:kotlinx-uuid-datetime:LATEST") +} +``` + +When declaring a table having UUID as Primary Key: + +```kotlin +// SQL DSL +object MyTable : KotlinxUUIDTable() { + // there is "id" property with the kotlin-uud type +} + +// DAO API +class MyTableEntity(id: EntityID) : KotlinxUUIDEntity(id) { + companion object : KotlinxUUIDEntityClass(MyTable) + +} +``` + +To declare a regular column, use `kotlinxUUID` function: + +```kotlin +object MyTable : Table() { + val something = kotlinxUUID("SOME_COLUMN") +} +``` + +Unfortunately, there is a function called `uuid` in the base class, inside Exposed, this is why we can't +overwrite/override it, so it may lead to confusion. The function `uuid` only works with `java.util.UUID`: + +```kotlin +object MyTable : Table() { + val column1 = kotlinxUUID("C1") // kotlinx.uuid.UUID + val column2 = uuid("C2") // java.util.UUID +} +``` diff --git a/kotlinx-uuid-datetime/build.gradle.kts b/kotlinx-uuid-datetime/build.gradle.kts new file mode 100644 index 0000000..4cdf491 --- /dev/null +++ b/kotlinx-uuid-datetime/build.gradle.kts @@ -0,0 +1,36 @@ +/* + * Copyright 2020-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2021 hfhbd and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +plugins { + id("kotlinJvm") + id("publish") + id("dokkaLicensee") + id("kover") +} + +kotlin.jvmToolchain(11) + +dependencies { + api(projects.kotlinxUuidCore) + api(libs.datetime) + + testImplementation(kotlin("test-junit")) + testRuntimeOnly(libs.slf4j) +} + +licensee { + allow("MIT") +} + +publishing { + publications.register("maven") { + from(components["java"]) + } +} + +java { + withJavadocJar() + withSourcesJar() +} diff --git a/kotlinx-uuid-datetime/src/main/kotlin/kotlinx/uuid/datetime/Dsl.kt b/kotlinx-uuid-datetime/src/main/kotlin/kotlinx/uuid/datetime/Dsl.kt new file mode 100644 index 0000000..cf5175a --- /dev/null +++ b/kotlinx-uuid-datetime/src/main/kotlin/kotlinx/uuid/datetime/Dsl.kt @@ -0,0 +1,20 @@ +package kotlinx.uuid.datetime + +import kotlinx.datetime.Clock +import kotlinx.datetime.Instant +import kotlinx.uuid.SecureRandom +import kotlinx.uuid.UUID +import kotlinx.uuid.UUIDExperimentalAPI +import kotlinx.uuid.UUIDv7 +import kotlinx.uuid.unixTimeStamp +import kotlin.random.Random + +@UUIDExperimentalAPI +public fun UUIDv7(random: Random = SecureRandom): UUID = + UUIDv7(timeStamp = Clock.System.now().toEpochMilliseconds(), random = random) + +/** + * The UUIDv7 48 bit big-endian unsigned number of Unix epoch timestamp in milliseconds + */ +@UUIDExperimentalAPI +public val UUID.instant: Instant get() = Instant.fromEpochMilliseconds(unixTimeStamp) diff --git a/kotlinx-uuid-datetime/src/test/kotlin/kotlinx/uuid/datetime/InstantTest.kt b/kotlinx-uuid-datetime/src/test/kotlin/kotlinx/uuid/datetime/InstantTest.kt new file mode 100644 index 0000000..19f5042 --- /dev/null +++ b/kotlinx-uuid-datetime/src/test/kotlin/kotlinx/uuid/datetime/InstantTest.kt @@ -0,0 +1,27 @@ +package kotlinx.uuid.datetime + +import kotlinx.datetime.Clock +import kotlinx.datetime.Instant +import kotlinx.uuid.UUIDExperimentalAPI +import kotlinx.uuid.UUIDv7 +import kotlin.test.Test +import kotlin.test.assertEquals + +@OptIn(UUIDExperimentalAPI::class) +class InstantTest { + + @Test + fun testConversionInstant() { + val timestamp = Clock.System.now() + val expected = timestamp.clampToMillisecondPrecision() + + val uuid = UUIDv7(timeStamp = timestamp.toEpochMilliseconds()) + val result = uuid.instant + + assertEquals(expected, result) + } + + private fun Instant.clampToMillisecondPrecision(): Instant { + return Instant.fromEpochMilliseconds(this.toEpochMilliseconds()) + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 15fa4e4..362dfb0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -40,3 +40,4 @@ include(":kotlinx-uuid-core") include(":kotlinx-uuid-exposed") include(":kotlinx-uuid-sqldelight") +include(":kotlinx-uuid-datetime")