MicroUtils/klock/src/commonMain/kotlin/korlibs/time/YearMonth.kt

66 lines
2.3 KiB
Kotlin

package korlibs.time
import korlibs.time.internal.Serializable
import kotlin.jvm.JvmInline
/**
* Represents a couple of [year] and [month].
*
* It is packed in a value class wrapping an Int to prevent allocations.
*/
@JvmInline
value class YearMonth(internal val internalPackedInfo: Int) : Serializable {
companion object {
@Suppress("MayBeConstant", "unused")
private const val serialVersionUID = 1L
/** Constructs a new [YearMonth] from the [year] and [month] components. */
operator fun invoke(year: Year, month: Month) = YearMonth(year.year, month.index1)
/** Constructs a new [YearMonth] from the [year] and [month] components. */
operator fun invoke(year: Int, month: Month) = YearMonth(year, month.index1)
/** Constructs a new [YearMonth] from the [year] and [month] components. */
operator fun invoke(year: Int, month1: Int) = YearMonth((year shl 4) or (month1 and 15))
}
/** The [year] part. */
val year: Year get() = Year(yearInt)
/** The [year] part as [Int]. */
val yearInt: Int get() = internalPackedInfo ushr 4
/** The [month] part. */
val month: Month get() = Month[month1]
/** The [month] part as [Int] where [Month.January] is 1. */
val month1: Int get() = internalPackedInfo and 15
/** Days in this [month] of this [year]. */
val days: Int get() = month.days(year)
/** Number of days since the start of the [year] to reach this [month]. */
val daysToStart: Int get() = month.daysToStart(year)
/** Number of days since the start of the [year] to reach next [month]. */
val daysToEnd: Int get() = month.daysToEnd(year)
operator fun plus(span: MonthSpan): YearMonth {
val newMonth = this.month1 + span.months
val yearAdjust = when {
newMonth > 12 -> +1
newMonth < 1 -> -1
else -> 0
}
return YearMonth(Year(this.yearInt + span.years + yearAdjust), Month[newMonth])
}
operator fun minus(span: MonthSpan): YearMonth = this + (-span)
override fun toString(): String = "$month $yearInt"
}
/**
* Creates a [YearMonth] representing [this] year and this [month].
*/
fun Year.withMonth(month: Month) = YearMonth(this, month)
/**
* Creates a [YearMonth] representing this [year] and [this] month.
*/
fun Month.withYear(year: Year) = YearMonth(year, this)