Skip to content

Commit

Permalink
Add kotlinx-datetime module (#198) (#351)
Browse files Browse the repository at this point in the history
* Add kotlinx-datetime module (#198)

* Migrate to MPP

* Add api

* Fix UUIDv7

---------

Co-authored-by: hfhbd <[email protected]>
  • Loading branch information
janseeger and hfhbd authored Jun 28, 2024
1 parent 80ee65f commit 5636665
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 15 deletions.
11 changes: 5 additions & 6 deletions detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<SmellBaseline>
<ManuallySuppressedIssues/>
<CurrentIssues>
<ID>FunctionNaming:Dsl.kt$@UUIDExperimentalAPI public fun UUIDv7(timeStamp: Instant = Clock.System.now(), random: Random = SecureRandom): UUID</ID>
<ID>FunctionNaming:UUID7.kt$@UUIDExperimentalAPI public fun UUIDv7(timeStamp: Long, random: Random = SecureRandom): UUID</ID>
<ID>MagicNumber:Encoding.kt$0xff</ID>
<ID>MagicNumber:Encoding.kt$56</ID>
Expand Down Expand Up @@ -85,18 +86,16 @@
<ID>MagicNumber:UUID.kt$UUID.Version.NAME_BASED_MD5$3</ID>
<ID>MagicNumber:UUID.kt$UUID.Version.NAME_BASED_SHA1$5</ID>
<ID>MagicNumber:UUID.kt$UUID.Version.RANDOM_BASED$4</ID>
<ID>MagicNumber:UUID7.kt$0x38</ID>
<ID>MagicNumber:UUID7.kt$0x3fffffffffffffffL</ID>
<ID>MagicNumber:UUID7.kt$0x7000L</ID>
<ID>MagicNumber:UUID7.kt$0x80L</ID>
<ID>MagicNumber:UUID7.kt$12</ID>
<ID>MagicNumber:UUID7.kt$16</ID>
<ID>MagicNumber:UUID7.kt$28672</ID>
<ID>MagicNumber:UUID7.kt$4095</ID>
<ID>MagicNumber:UUID7.kt$62</ID>
<ID>MatchingDeclarationName:CommonParcelable.apple.kt$CommonParcelable</ID>
<ID>MatchingDeclarationName:CommonParcelable.js.kt$CommonParcelable</ID>
<ID>MatchingDeclarationName:CommonParcelable.jvm.kt$CommonParcelable</ID>
<ID>MatchingDeclarationName:CommonParcelable.linux.kt$CommonParcelable</ID>
<ID>MatchingDeclarationName:CommonParcelable.ming.kt$CommonParcelable</ID>
<ID>TooManyFunctions:SHA1.kt$SHA1</ID>
<ID>VariableNaming:UUID7.kt$val rand_a = random.nextBits(12).toLong()</ID>
<ID>VariableNaming:UUID7.kt$val rand_a = helper.timeStamp and 4095</ID>
</CurrentIssues>
</SmellBaseline>
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,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 = "0.6.0" }

androidx-test-runner = { module = "androidx.test:runner", version = "1.6.1" }

[plugins]
Expand Down
5 changes: 5 additions & 0 deletions kotlin-js-store/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
"@jridgewell/resolve-uri" "3.1.0"
"@jridgewell/sourcemap-codec" "1.4.14"

"@js-joda/[email protected]":
version "3.2.0"
resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-3.2.0.tgz#3e61e21b7b2b8a6be746df1335cf91d70db2a273"
integrity sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg==

"@socket.io/component-emitter@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
Expand Down
14 changes: 7 additions & 7 deletions kotlinx-uuid-core/src/commonMain/kotlin/kotlinx/uuid/UUID7.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ public fun UUIDv7(timeStamp: Long, random: Random = SecureRandom): UUID {
require(timeStamp <= UNIX_48_TIMESTAMP) {
"timeStamp $timeStamp must be <= 48 bits, was $timeStamp."
}
val helper = random.nextUUID()
val leftTimeStamp = timeStamp shl 16
val rand_a = random.nextBits(12).toLong()
val timeStampAndVersionRaw = (leftTimeStamp or rand_a) and -0xf001L or 0x7000L

// set variant to 4 or 5
// we keep the lower variant bit random as it is defined as "don't care"
val clockSequenceVariantAndNodeRaw: Long = random.nextLong() and
0x3fffffffffffffffL or (0x80L shl 0x38)
// set version to 0b0111
val leftTimeStampAndVersion = leftTimeStamp or 28672
val rand_a = helper.timeStamp and 4095
val timeStampAndVersionRaw = leftTimeStampAndVersion or rand_a
// set variant to 0b10
val clockSequenceVariantAndNodeRaw = (2L shl 62) or (helper.clockSequenceVariantAndNodeRaw ushr 2)

return create(timeStampAndVersionRaw, clockSequenceVariantAndNodeRaw)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ class UUIDv7Test {

assertEquals(1645557742000, one.unixTimeStamp)
assertEquals(1645557742000, two.unixTimeStamp)
assertEquals("017f22e2-79b0-735c-9e4a-5c16cd08736d", one.toString())
assertEquals("017f22e2-79b0-7493-a342-1cdb22b5d84b", one.toString())
assertEquals(7, one.versionNumber)
assertEquals(4, one.variant)
}
}
21 changes: 21 additions & 0 deletions kotlinx-uuid-datetime/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Module kotlinx-uuid-datetime

Provides support for UUIDv7 using kotlinx-datetime.

```kotlin
dependencies {
implementation("app.softwork:kotlinx-uuid-datetime:LATEST")
}
```

UUIDv7 with the current timestamp using `Clock.System` and default SecureRandom can be created using:

```kotlin
val uuid = UUIDv7()
```

When processing existing UUIDv7s, the timestamp bits can be interpreted as an Instant with millisecond precision using:

```kotlin
UUIDv7().instant
```
6 changes: 6 additions & 0 deletions kotlinx-uuid-datetime/api/kotlinx-uuid-datetime.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public final class kotlinx/uuid/datetime/DslKt {
public static final fun UUIDv7 (Lkotlinx/datetime/Instant;Lkotlin/random/Random;)Lkotlinx/uuid/UUID;
public static synthetic fun UUIDv7$default (Lkotlinx/datetime/Instant;Lkotlin/random/Random;ILjava/lang/Object;)Lkotlinx/uuid/UUID;
public static final fun getInstant (Lkotlinx/uuid/UUID;)Lkotlinx/datetime/Instant;
}

24 changes: 24 additions & 0 deletions kotlinx-uuid-datetime/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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("kotlinMPP")
id("publish")
id("dokkaLicensee")
}

kotlin.sourceSets {
commonMain {
dependencies {
api(projects.kotlinxUuidCore)
api(libs.datetime)
}
}
commonTest {
dependencies {
implementation(kotlin("test"))
}
}
}
Original file line number Diff line number Diff line change
@@ -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(timeStamp: Instant = Clock.System.now(), random: Random = SecureRandom): UUID =
UUIDv7(timeStamp = timeStamp.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)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package kotlinx.uuid.datetime

import kotlinx.datetime.Instant
import kotlinx.uuid.UUIDExperimentalAPI
import kotlin.random.Random
import kotlin.test.Test
import kotlin.test.assertEquals

@OptIn(UUIDExperimentalAPI::class)
class InstantTest {

@Test
fun testConversionInstant() {
val timestamp = Instant.parse("2020-02-20T10:21:42Z")
val uuid = UUIDv7(timeStamp = timestamp, random = Random(4242))
assertEquals(timestamp, uuid.instant)
assertEquals("0170621e-0ef0-7493-a342-1cdb22b5d84b", uuid.toString())
assertEquals(7, uuid.versionNumber)
}
}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ include(":kotlinx-uuid-core")

include(":kotlinx-uuid-exposed")
include(":kotlinx-uuid-sqldelight")
include(":kotlinx-uuid-datetime")

0 comments on commit 5636665

Please sign in to comment.