Skip to content

Commit

Permalink
feature: move time-related feature to separate kommons-time module
Browse files Browse the repository at this point in the history
  • Loading branch information
bkahlert committed Mar 5, 2023
1 parent 54711b6 commit 0120697
Show file tree
Hide file tree
Showing 34 changed files with 381 additions and 114 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- Kotlin 1.8.10
- Ktor 2.2.3
- Kotlinx.serialization to 1.5.0
- moved time-related feature to separate kommons-time module

### Deprecated

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- [Kommons Logging](kommons-logging) … for simple logging *(only **logging-core** included by default)*
- [Kommons Test](kommons-test) … to ease testing
- **[Kommons Text](kommons-text) … for Unicode-aware text operations**
- [Kommons Time](kommons-time)[KotlinX multiplatform date/time library](https://github.com/Kotlin/kotlinx-datetime) extension
- **[Kommons URI](kommons-uri) … for handling (Data) URIs**

The modules in **bold** are included in the `Kommons` module.
Expand Down
2 changes: 1 addition & 1 deletion kommons-bom/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## About

**Kommons BOM** is a platform library with the version of all Kommons modules.
**Kommons BOM** is a platform library with the version of most Kommons modules.

## Installation / setup

Expand Down
17 changes: 0 additions & 17 deletions kommons-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,23 +120,6 @@ Iterate any type of closed ranges using `asIterable`.
.map { it.toInt() } // [-4, 4, 13, 22, 31, 40]
```

### Time Operations

```kotlin
Now + 2.seconds // 2 seconds in the future
Today - 3.days // 3 days in the past
Yesterday - 2.days // 3 days in the past
Tomorrow + 1.days // the day after tomorrow
Instant.parse("1910-06-22T13:00:00Z") + 5.minutes // 1910-06-22T12:05:00Z
LocalDate.parse("1910-06-22") - 2.days // 1910-06-20
SystemLocations.Temp.createTempFile().age // < 1ms

Now.toMomentString() // "now"
(Now - 12.hours).toMomentString() // "12h ago"
(Now + 3.days).toMomentString() // "in 3d"
(Today - 1.days).toMomentString() // "yesterday"
```

### Byte Operations

#### toHexadecimalString(), toOctalString(), toBinaryString()
Expand Down
8 changes: 2 additions & 6 deletions kommons-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@ plugins {
id("kommons-multiplatform-library-conventions")
}

description = "Kommons Core is a Kotlin Multiplatform Library that offers shared features for all Kommons modules."
description = "Kommons Core is a Kotlin Multiplatform Library that offers shared features for most Kommons modules."

kotlin {

@Suppress("UNUSED_VARIABLE")
sourceSets {
val commonMain by getting {
dependencies {
api(libs.kotlinx.datetime)
}
}
val commonMain by getting
val commonTest by getting {
dependencies {
implementation(project(":kommons-test"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.bkahlert.kommons

import com.bkahlert.kommons.RoundingMode.Ceiling
import kotlinx.datetime.Instant
import kotlin.random.Random

private const val EMPTY_STRING: String = ""
Expand All @@ -10,28 +8,13 @@ private const val EMPTY_STRING: String = ""
public val String.Companion.EMPTY: String get() = EMPTY_STRING

/** Creates a random string of the specified [length] made up of the specified [allowedCharacters]. */
public fun randomString(length: Int = 16, vararg allowedCharacters: kotlin.Char = (('0'..'9') + ('a'..'z') + ('A'..'Z')).toCharArray()): String =
public fun randomString(length: Int = 16, vararg allowedCharacters: Char = (('0'..'9') + ('a'..'z') + ('A'..'Z')).toCharArray()): String =
buildString(length) { repeat(length) { append(allowedCharacters[Random.nextInt(0, allowedCharacters.size)]) } }

/** Returns an Emoji representation of this value. */
public fun Any?.asEmoji(): String = when (this) {
null -> ""
true -> ""
false -> ""
is Instant -> asEmoji()
else -> "🔣"
}

/** Returns an Emoji representation of this [Instant] and the specified [roundingMode]. */
public fun Instant.asEmoji(roundingMode: RoundingMode = Ceiling): String {
val hour = utcHours
val minute = utcMinutes
return when ((roundingMode(minute.toDouble(), 30.0) / 30.0).toInt()) {
0 -> fullHourClocks[hour]
1 -> halfHourClocks[hour]
else -> fullHourClocks[hour + 1]
}
}

private val fullHourClocks = listOf("🕛", "🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚").withNegativeIndices()
private val halfHourClocks = listOf("🕧", "🕜", "🕝", "🕞", "🕟", "🕠", "🕡", "🕢", "🕣", "🕤", "🕥", "🕦").withNegativeIndices()
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package com.bkahlert.kommons

import com.bkahlert.kommons.RoundingMode.Ceiling
import com.bkahlert.kommons.RoundingMode.Floor
import com.bkahlert.kommons.RoundingMode.HalfUp
import com.bkahlert.kommons.test.testAll
import io.kotest.inspectors.forAll
import io.kotest.matchers.collections.shouldContain
Expand Down Expand Up @@ -30,17 +27,6 @@ class StringsKtTest {
null.asEmoji() shouldBe ""
true.asEmoji() shouldBe ""
false.asEmoji() shouldBe ""

instant0202.asEmoji() shouldBe "🕝"
instant0202.asEmoji(Ceiling) shouldBe "🕝"
instant0202.asEmoji(Floor) shouldBe "🕑"
instant0202.asEmoji(HalfUp) shouldBe "🕑"

instant2232.asEmoji() shouldBe "🕚"
instant2232.asEmoji(Ceiling) shouldBe "🕚"
instant2232.asEmoji(Floor) shouldBe "🕥"
instant2232.asEmoji(HalfUp) shouldBe "🕥"

"other".asEmoji() shouldBe "🔣"
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
package com.bkahlert.kommons.exec

import com.bkahlert.kommons.Now
import com.bkahlert.kommons.debug.asString
import com.bkahlert.kommons.text.LineSeparators.removeTrailingLineSeparator
import com.bkahlert.kommons.text.startSpaced
import kotlinx.datetime.Instant
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.nio.charset.Charset
import java.time.Instant
import kotlin.reflect.full.memberFunctions
import kotlin.reflect.jvm.isAccessible
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds

/** [java.lang.Process] wrapper with extended features such as access to its [state]. */
public open class Process(
private val process: java.lang.Process,
private val commandLine: CommandLine? = null,
/** Moment the process started. */
public val start: Instant = Now,
public val start: Instant = Instant.now(),
) : java.lang.Process() {

public constructor(process: Process) : this(
Expand Down Expand Up @@ -100,7 +100,7 @@ public open class Process(
public val end: Instant

/** [Duration] the process took to execute. */
public val runtime: Duration get() = end - start
public val runtime: Duration get() = (end.toEpochMilli() - start.toEpochMilli()).milliseconds

/** Exit code the process terminated with. */
public val exitCode: Int get() = process.exitValue()
Expand Down Expand Up @@ -147,7 +147,7 @@ public open class Process(
/** State of a process that terminated successfully. */
public inner class Succeeded : ExitState {
override val process: Process get() = this@Process
override val end: Instant = Now
override val end: Instant = Instant.now()
override val status: String = "Process${pid?.toString().startSpaced} terminated successfully within $runtime"
override fun toString(): String = status

Expand All @@ -158,7 +158,7 @@ public open class Process(
/** State of a process that terminated erroneously. */
public inner class Failed : ExitState {
override val process: Process get() = this@Process
override val end: Instant = Now
override val end: Instant = Instant.now()
override val status: String = "Process${pid?.toString().startSpaced} terminated after $runtime with exit code $exitCode"
override fun toString(): String = status

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.bkahlert.kommons.exec

import com.bkahlert.kommons.Now
import com.bkahlert.kommons.Timestamp
import com.bkahlert.kommons.randomString
import com.bkahlert.kommons.test.shouldMatchGlob
import com.bkahlert.kommons.test.testAll
import com.bkahlert.kommons.text.LineSeparators.removeTrailingLineSeparator
import com.bkahlert.kommons.time.Now
import com.bkahlert.kommons.time.Timestamp
import io.kotest.assertions.throwables.shouldNotThrowAny
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.inspectors.forAll
Expand Down Expand Up @@ -40,8 +40,8 @@ class ProcessTest {
@Test fun start() = testAll {
val start = Now
Process(ProcessBuilder(shellCommand, *shellArguments, "echo test")).start should {
it.toEpochMilliseconds() shouldBeGreaterThanOrEqualTo start.toEpochMilliseconds()
it.toEpochMilliseconds() shouldBeLessThanOrEqualTo Timestamp
it.toEpochMilli() shouldBeGreaterThanOrEqualTo start.toEpochMilliseconds()
it.toEpochMilli() shouldBeLessThanOrEqualTo Timestamp
}
}

Expand Down Expand Up @@ -85,7 +85,7 @@ class ProcessTest {
waitFor()
} should {
it.exitValue() shouldNotBe 0
Now.minus(it.start) shouldBeLessThan 5.seconds
(System.currentTimeMillis() - it.start.toEpochMilli()).milliseconds shouldBeLessThan 5.seconds
}
}

Expand Down Expand Up @@ -127,9 +127,9 @@ class ProcessTest {
val succeededProcess = Process.succeeded()
succeededProcess.exitState.shouldBeInstanceOf<Process.Succeeded>() should {
it.process shouldBeSameInstanceAs succeededProcess
it.start.minus(it.process.start) shouldBeLessThan 10.milliseconds
it.end.toEpochMilliseconds() shouldBeLessThanOrEqualTo Timestamp
it.runtime shouldBe it.end - it.start
it.start.toEpochMilli() - it.process.start.toEpochMilli() shouldBeLessThan 10
it.end.toEpochMilli() shouldBeLessThanOrEqualTo System.currentTimeMillis()
it.runtime shouldBe (it.end.toEpochMilli() - it.start.toEpochMilli()).milliseconds
it.exitCode shouldBe 0
it.status shouldMatchGlob "Process* terminated successfully within *"
it.toString() shouldBe it.status
Expand All @@ -141,9 +141,9 @@ class ProcessTest {
val failedProcess = Process.failed()
failedProcess.exitState.shouldBeInstanceOf<Process.Failed>() should {
it.process shouldBeSameInstanceAs failedProcess
it.start.minus(it.process.start) shouldBeLessThan 10.milliseconds
it.end.toEpochMilliseconds() shouldBeLessThanOrEqualTo Timestamp
it.runtime shouldBe it.end - it.start
it.start.toEpochMilli() - it.process.start.toEpochMilli() shouldBeLessThan 10
it.end.toEpochMilli() shouldBeLessThanOrEqualTo System.currentTimeMillis()
it.runtime shouldBe (it.end.toEpochMilli() - it.start.toEpochMilli()).milliseconds
it.exitCode shouldBe 42
it.status shouldMatchGlob "Process* terminated after * with exit code 42"
it.toString() shouldBe it.status
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.bkahlert.kommons.exec

import com.bkahlert.kommons.Timestamp
import org.slf4j.Logger
import org.slf4j.Marker
import org.slf4j.event.Level
Expand Down Expand Up @@ -46,9 +45,9 @@ class RecordingLogger(
vararg argumentArray: Any?,
marker: Marker? = null,
threadName: String = Thread.currentThread().name,
timeStamp: Long = Timestamp,
timeStamp: Long = System.currentTimeMillis(),
throwable: Throwable? = null,
): Unit {
) {
_events.add(RecordedLoggingEvent(level, marker, getName(), message, threadName, argumentArray.asList(), timeStamp, throwable))
}

Expand Down
Loading

0 comments on commit 0120697

Please sign in to comment.