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

commonMain.io.islandtime.ranges.TimePointInterval.kt Maven / Gradle / Ivy

The newest version!
package io.islandtime.ranges

import io.islandtime.base.TimePoint
import io.islandtime.measures.*
import io.islandtime.measures.internal.minusWithOverflow
import io.islandtime.ranges.internal.*

/**
 * A half-open interval of time points.
 */
abstract class TimePointInterval> internal constructor(
    override val start: T,
    override val endExclusive: T
) : Interval {

    override val endInclusive: T
        get() = if (hasUnboundedEnd()) endExclusive else endExclusive - 1.nanoseconds

    override fun equals(other: Any?): Boolean {
        return other is TimePointInterval<*> && (isEmpty() && other.isEmpty() ||
            ((hasUnboundedStart() && other.hasUnboundedStart()) || start == other.start) &&
            ((hasUnboundedEnd() && other.hasUnboundedEnd()) || endExclusive == other.endExclusive))
    }

    override fun hashCode(): Int {
        return if (isEmpty()) -1 else (31 * start.hashCode() + endExclusive.hashCode())
    }

    override fun contains(value: T): Boolean {
        return (value >= start || hasUnboundedStart()) && (value < endExclusive || hasUnboundedEnd())
    }

    override fun isEmpty(): Boolean = start >= endExclusive

    /**
     * Converts this interval into a [Duration] of the same length.
     * @throws UnsupportedOperationException if the interval isn't bounded
     */
    fun asDuration(): Duration {
        return when {
            isEmpty() -> Duration.ZERO
            isBounded() -> durationBetween(start, endExclusive)
            else -> throwUnboundedIntervalException()
        }
    }

    /**
     * The number of 24-hour days in this interval.
     * @throws UnsupportedOperationException if the interval isn't bounded
     */
    open val lengthInDays: LongDays
        get() = when {
            isEmpty() -> 0L.days
            isBounded() -> daysBetween(start, endExclusive)
            else -> throwUnboundedIntervalException()
        }

    /**
     * The number of whole hours in this interval.
     * @throws UnsupportedOperationException if the interval isn't bounded
     */
    val lengthInHours: LongHours
        get() = when {
            isEmpty() -> 0L.hours
            isBounded() -> hoursBetween(start, endExclusive)
            else -> throwUnboundedIntervalException()
        }

    /**
     * The number of whole minutes in this interval.
     * @throws UnsupportedOperationException if the interval isn't bounded
     */
    val lengthInMinutes: LongMinutes
        get() = when {
            isEmpty() -> 0L.minutes
            isBounded() -> minutesBetween(start, endExclusive)
            else -> throwUnboundedIntervalException()
        }

    /**
     * The number of whole seconds in this interval.
     * @throws UnsupportedOperationException if the interval isn't bounded
     */
    val lengthInSeconds: LongSeconds
        get() = when {
            isEmpty() -> 0L.seconds
            isBounded() -> secondsBetween(start, endExclusive)
            else -> throwUnboundedIntervalException()
        }

    /**
     * The number of whole milliseconds in this interval.
     * @throws UnsupportedOperationException if the interval isn't bounded
     */
    val lengthInMilliseconds: LongMilliseconds
        get() = when {
            isEmpty() -> 0L.milliseconds
            isBounded() -> millisecondsBetween(start, endExclusive)
            else -> throwUnboundedIntervalException()
        }

    /**
     * The number of whole microseconds in this interval.
     * @throws UnsupportedOperationException if the interval isn't bounded
     */
    val lengthInMicroseconds: LongMicroseconds
        get() = when {
            isEmpty() -> 0L.microseconds
            isBounded() -> microsecondsBetween(start, endExclusive)
            else -> throwUnboundedIntervalException()
        }

    /**
     * The number of whole nanoseconds in this interval.
     * @throws UnsupportedOperationException if the interval isn't bounded
     */
    val lengthInNanoseconds: LongNanoseconds
        get() = when {
            isEmpty() -> 0L.nanoseconds
            isBounded() -> nanosecondsBetween(start, endExclusive)
            else -> throwUnboundedIntervalException()
        }
}

/**
 * Checks if this interval contains [value]. This will always return `false` if [value] is `null`.
 */
operator fun > TimePointInterval.contains(value: TimePoint<*>?): Boolean {
    return value != null &&
        (value >= start || hasUnboundedStart()) &&
        (value < endExclusive || hasUnboundedEnd())
}

/**
 * Gets the [Duration] between two time points.
 */
fun  durationBetween(start: TimePoint, endExclusive: TimePoint): Duration {
    val secondDiff = endExclusive.secondsSinceUnixEpoch - start.secondsSinceUnixEpoch
    val nanoDiff =
        endExclusive.additionalNanosecondsSinceUnixEpoch minusWithOverflow start.additionalNanosecondsSinceUnixEpoch
    return durationOf(secondDiff, nanoDiff)
}

/**
 * Gets the number of 24-hour days between two time points.
 */
fun  daysBetween(start: TimePoint, endExclusive: TimePoint): LongDays {
    return secondsBetween(start, endExclusive).inDays
}

/**
 * Gets the number of whole hours between two time points.
 */
fun  hoursBetween(start: TimePoint, endExclusive: TimePoint): LongHours {
    return secondsBetween(start, endExclusive).inHours
}

/**
 * Gets the number of whole minutes between two time points.
 */
fun  minutesBetween(start: TimePoint, endExclusive: TimePoint): LongMinutes {
    return secondsBetween(start, endExclusive).inMinutes
}

/**
 * Gets the number of whole seconds between two time points.
 * @throws ArithmeticException if the result overflows
 */
fun  secondsBetween(start: TimePoint, endExclusive: TimePoint): LongSeconds {
    return secondsBetween(
        start.secondsSinceUnixEpoch,
        start.additionalNanosecondsSinceUnixEpoch,
        endExclusive.secondsSinceUnixEpoch,
        endExclusive.additionalNanosecondsSinceUnixEpoch
    )
}

/**
 * Gets the number of whole milliseconds between two time points.
 * @throws ArithmeticException if the result overflows
 */
fun  millisecondsBetween(
    start: TimePoint,
    endExclusive: TimePoint
): LongMilliseconds {
    return millisecondsBetween(
        start.secondsSinceUnixEpoch,
        start.additionalNanosecondsSinceUnixEpoch,
        endExclusive.secondsSinceUnixEpoch,
        endExclusive.additionalNanosecondsSinceUnixEpoch
    )
}

/**
 * Gets the number of whole microseconds between two time points.
 *  @throws ArithmeticException if the result overflows
 */
fun  microsecondsBetween(
    start: TimePoint,
    endExclusive: TimePoint
): LongMicroseconds {
    return microsecondsBetween(
        start.secondsSinceUnixEpoch,
        start.additionalNanosecondsSinceUnixEpoch,
        endExclusive.secondsSinceUnixEpoch,
        endExclusive.additionalNanosecondsSinceUnixEpoch
    )
}

/**
 * Gets the number of nanoseconds between two time points.
 * @throws ArithmeticException if the result overflows
 */
fun  nanosecondsBetween(
    start: TimePoint,
    endExclusive: TimePoint
): LongNanoseconds {
    return nanosecondsBetween(
        start.secondsSinceUnixEpoch,
        start.additionalNanosecondsSinceUnixEpoch,
        endExclusive.secondsSinceUnixEpoch,
        endExclusive.additionalNanosecondsSinceUnixEpoch
    )
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy