All Downloads are FREE. Search and download functionalities are using the official Maven repository.

run.smt.ktest.util.duration.duration.kt Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
package run.smt.ktest.util.duration

import java.time.Duration
import java.time.temporal.ChronoUnit
import java.time.temporal.TemporalUnit

/**
 * Usage example: ```

val testTime = inSeconds { 10.days() + 2.hours() + 3.minutes() + 15.seconds() + 2.millis() }

println(inSeconds { 2.minutes() })
println(inDays { 240.hours() })
println(inMillis { testTime.seconds().show() })
println(inSeconds { testTime.seconds().show() })
println(inMinutes { testTime.seconds().show() })
println(inHours { testTime.seconds().show() })
println(inDays { testTime.seconds().show() })

 * ```
 */

val infinity = Long.MAX_VALUE
val infiniteDuration = inNanos { infinity.nanos().toDuration() }

abstract class TimeUnit> {
    companion object {
        data class PrettyText(
            val text: String,
            val remainder: Long
        )
    }

    operator fun  invoke(contextAware: T.() -> R): R = self().contextAware()

    abstract fun unitName(): String
    abstract fun shortUnitName(): String
    abstract fun temporalUnit(): TemporalUnit

    abstract fun Int.nanos(): Int
    abstract fun Int.millis(): Int
    abstract fun Int.seconds(): Int
    abstract fun Int.minutes(): Int
    abstract fun Int.hours(): Int
    abstract fun Int.days(): Int

    abstract fun Long.nanos(): Long
    abstract fun Long.millis(): Long
    abstract fun Long.seconds(): Long
    abstract fun Long.minutes(): Long
    abstract fun Long.hours(): Long
    abstract fun Long.days(): Long

    fun Long.toDuration(): Duration = Duration.of(this, temporalUnit())
    fun Int.toDuration(): Duration = toLong().toDuration()

    protected abstract fun self(): T
    protected abstract fun  internalShow(numberToShow: T): PrettyText

    protected inline fun > parametrizedShow(
        greaterContext: P,
        crossinline selfUnit: P.(Long) -> Long,
        crossinline greaterUnit: Long.() -> Long
    ): (T) -> PrettyText = { numberToShow ->
        val n = numberToShow.toLong()
        val greaterValue = greaterContext { selfUnit(n) }
        if (greaterValue == 0L) {
            PrettyText("", numberToShow.toLong())
        } else {
            PrettyText(greaterContext { greaterValue.show() }, n - greaterValue.greaterUnit())
        }
    }

    fun  T.show(): String {
        val internal = internalShow(this)
        val selfValue = "${internal.remainder}${shortUnitName()}"
        if (internal.text.isBlank()) {
            return selfValue
        }
        return "${internal.text} $selfValue"
    }
}

inline fun  inNanos(computation: NanosBase.() -> T): T = NanosBase.computation()

object NanosBase : TimeUnit() {
    override fun self() = this

    override fun Int.nanos() = this
    override fun Int.millis() = 1000000 * nanos()
    override fun Int.seconds() = 1000 * millis()
    override fun Int.minutes() = 60 * seconds()
    override fun Int.hours() = 60 * minutes()
    override fun Int.days() = 24 * hours()

    override fun Long.nanos() = this
    override fun Long.millis() = 1000000L * nanos()
    override fun Long.seconds() = 1000L * millis()
    override fun Long.minutes() = 60L * seconds()
    override fun Long.hours() = 60L * minutes()
    override fun Long.days() = 24L * hours()

    override fun unitName(): String = "nanosecond"

    override fun shortUnitName(): String = "n"

    override fun temporalUnit(): TemporalUnit = ChronoUnit.NANOS

    override fun  internalShow(numberToShow: T): PrettyText {
        return (NanosBase.parametrizedShow(
            MillisBase,
            { it.nanos() },
            { millis() }
        ))(numberToShow)
    }
}

inline fun  inMillis(computation: MillisBase.() -> T): T = MillisBase.computation()

object MillisBase : TimeUnit() {
    override fun self() = this

    override fun Int.nanos() = millis() / 1000000
    override fun Int.millis() = this
    override fun Int.seconds() = 1000 * millis()
    override fun Int.minutes() = 60 * seconds()
    override fun Int.hours() = 60 * minutes()
    override fun Int.days() = 24 * hours()

    override fun Long.nanos() = millis() / 1000000
    override fun Long.millis() = this
    override fun Long.seconds() = 1000L * millis()
    override fun Long.minutes() = 60L * seconds()
    override fun Long.hours() = 60L * minutes()
    override fun Long.days() = 24L * hours()

    override fun unitName(): String = "millisecond"

    override fun shortUnitName(): String = "ms"

    override fun temporalUnit(): TemporalUnit = ChronoUnit.MILLIS

    override fun  internalShow(numberToShow: T): PrettyText {
        return parametrizedShow(
            SecondsBase,
            { it.millis() },
            { seconds() }
        )(numberToShow)
    }
}

inline fun  inSeconds(computation: SecondsBase.() -> T): T = SecondsBase.computation()

object SecondsBase : TimeUnit() {
    override fun self() = this

    override fun Int.nanos() = millis() / 1000000
    override fun Int.millis() = seconds() / 1000
    override fun Int.seconds() = this
    override fun Int.minutes() = 60 * seconds()
    override fun Int.hours() = 60 * minutes()
    override fun Int.days() = 24 * hours()

    override fun Long.nanos() = millis() / 1000000
    override fun Long.millis() = seconds() / 1000
    override fun Long.seconds() = this
    override fun Long.minutes() = 60L * seconds()
    override fun Long.hours() = 60L * minutes()
    override fun Long.days() = 24L * hours()

    override fun unitName(): String = "second"

    override fun shortUnitName(): String = "s"

    override fun temporalUnit(): TemporalUnit = ChronoUnit.SECONDS

    override fun  internalShow(numberToShow: T): PrettyText {
        return parametrizedShow(
            MinutesBase,
            { it.seconds() },
            { minutes() }
        )(numberToShow)
    }
}

inline fun  inMinutes(computation: MinutesBase.() -> T): T = MinutesBase.computation()

object MinutesBase : TimeUnit() {
    override fun self() = this

    override fun Int.nanos() = millis() / 1000000
    override fun Int.millis() = seconds() / 1000
    override fun Int.seconds() = minutes() / 60
    override fun Int.minutes() = this
    override fun Int.hours() = 60 * minutes()
    override fun Int.days() = 24 * hours()

    override fun Long.nanos() = millis() / 1000000
    override fun Long.millis() = seconds() / 1000
    override fun Long.seconds() = minutes() / 60
    override fun Long.minutes() = this
    override fun Long.hours() = 60 * minutes()
    override fun Long.days() = 24 * hours()

    override fun unitName(): String = "minute"

    override fun shortUnitName(): String = "m"

    override fun temporalUnit(): TemporalUnit = ChronoUnit.MINUTES

    override fun  internalShow(numberToShow: T): PrettyText {
        return parametrizedShow(
            HoursBase,
            { it.minutes() },
            { hours() }
        )(numberToShow)
    }
}

inline fun  inHours(computation: HoursBase.() -> T): T = HoursBase.computation()

object HoursBase : TimeUnit() {
    override fun self() = this

    override fun Int.nanos() = millis() / 1000000
    override fun Int.millis() = seconds() / 1000
    override fun Int.seconds() = minutes() / 60
    override fun Int.minutes() = hours() / 60
    override fun Int.hours() = this
    override fun Int.days() = 24 * hours()

    override fun Long.nanos() = millis() / 1000000
    override fun Long.millis() = seconds() / 1000
    override fun Long.seconds() = minutes() / 60
    override fun Long.minutes() = hours() / 60
    override fun Long.hours() = this
    override fun Long.days() = 24 * hours()

    override fun unitName(): String = "hour"

    override fun shortUnitName(): String = "h"

    override fun temporalUnit(): TemporalUnit = ChronoUnit.HOURS

    override fun  internalShow(numberToShow: T): PrettyText {
        return parametrizedShow(
            DaysBase,
            { it.hours() },
            { days() }
        )(numberToShow)
    }
}

inline fun  inDays(computation: DaysBase.() -> T): T = DaysBase.computation()

object DaysBase : TimeUnit() {
    override fun self() = this

    override fun Int.nanos() = millis() / 1000000
    override fun Int.millis() = seconds() / 1000
    override fun Int.seconds() = minutes() / 60
    override fun Int.minutes() = hours() / 60
    override fun Int.hours() = days() / 24
    override fun Int.days() = this

    override fun Long.nanos() = millis() / 1000000
    override fun Long.millis() = seconds() / 1000
    override fun Long.seconds() = minutes() / 60
    override fun Long.minutes() = hours() / 60
    override fun Long.hours() = days() / 24
    override fun Long.days() = this

    override fun unitName(): String = "day"

    override fun shortUnitName(): String = "D"

    override fun temporalUnit(): TemporalUnit = ChronoUnit.DAYS

    override fun  internalShow(numberToShow: T): PrettyText {
        return PrettyText("", numberToShow.toLong())
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy