darwinMain.io.islandtime.darwin.Conversions.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core-metadata Show documentation
Show all versions of core-metadata Show documentation
A multiplatform library for working with dates and times
The newest version!
package io.islandtime.darwin
import io.islandtime.*
import io.islandtime.base.TimePoint
import io.islandtime.internal.MICROSECONDS_PER_SECOND
import io.islandtime.internal.MILLISECONDS_PER_SECOND
import io.islandtime.internal.NANOSECONDS_PER_SECOND
import io.islandtime.measures.*
import io.islandtime.ranges.InstantInterval
import io.islandtime.ranges.TimePointInterval
import io.islandtime.ranges.until
import io.islandtime.zone.TimeZoneRulesException
import kotlinx.cinterop.convert
import platform.Foundation.*
/**
* Converts this year to an equivalent `NSDateComponents` object.
* @param includeCalendar `true` if the resulting `NSDateComponents` should include the ISO-8601 calendar
* @return an equivalent `NSDateComponents` object
*/
fun Year.toNSDateComponents(includeCalendar: Boolean = false): NSDateComponents {
return NSDateComponents().also {
if (includeCalendar) it.calendar = NSCalendar(NSCalendarIdentifierISO8601)
it.year = value.convert()
}
}
/**
* Converts this year-month to an equivalent `NSDateComponents` object.
* @param includeCalendar `true` if the resulting `NSDateComponents` should include the ISO-8601 calendar
* @return an equivalent `NSDateComponents` object
*/
fun YearMonth.toNSDateComponents(includeCalendar: Boolean = false): NSDateComponents {
return NSDateComponents().also {
if (includeCalendar) it.calendar = NSCalendar(NSCalendarIdentifierISO8601)
it.year = year.convert()
it.month = monthNumber.convert()
}
}
/**
* Converts this date to an equivalent `NSDateComponents` object.
* @param includeCalendar `true` if the resulting `NSDateComponents` should include the ISO-8601 calendar
* @return an equivalent `NSDateComponents` object
*/
fun Date.toNSDateComponents(includeCalendar: Boolean = false): NSDateComponents {
return NSDateComponents().also {
if (includeCalendar) it.calendar = NSCalendar(NSCalendarIdentifierISO8601)
it.populateFrom(this)
}
}
/**
* Converts this time to an equivalent `NSDateComponents` object.
* @param includeCalendar `true` if the resulting `NSDateComponents` should include the ISO-8601 calendar
* @return an equivalent `NSDateComponents` object
*/
fun Time.toNSDateComponents(includeCalendar: Boolean = false): NSDateComponents {
return NSDateComponents().also {
if (includeCalendar) it.calendar = NSCalendar(NSCalendarIdentifierISO8601)
it.populateFrom(this)
}
}
/**
* Converts this date-time to an equivalent `NSDateComponents` object.
* @param includeCalendar `true` if the resulting `NSDateComponents` should include the ISO-8601 calendar
* @return an equivalent `NSDateComponents` object
*/
fun DateTime.toNSDateComponents(includeCalendar: Boolean = false): NSDateComponents {
return NSDateComponents().also {
if (includeCalendar) it.calendar = NSCalendar(NSCalendarIdentifierISO8601)
it.populateFrom(this)
}
}
/**
* Converts this time to an equivalent `NSDateComponents` object.
* @param includeCalendar `true` if the resulting `NSDateComponents` should include the ISO-8601 calendar
* @return an equivalent `NSDateComponents` object
*/
fun OffsetTime.toNSDateComponents(includeCalendar: Boolean = false): NSDateComponents {
return NSDateComponents().also {
if (includeCalendar) it.calendar = NSCalendar(NSCalendarIdentifierISO8601)
it.populateFrom(time)
it.timeZone = offset.toNSTimeZone()
}
}
/**
* Converts this date-time to an equivalent `NSDateComponents` object.
* @param includeCalendar `true` if the resulting `NSDateComponents` should include the ISO-8601 calendar
* @return an equivalent `NSDateComponents` object
*/
fun OffsetDateTime.toNSDateComponents(includeCalendar: Boolean = false): NSDateComponents {
return NSDateComponents().also {
if (includeCalendar) it.calendar = NSCalendar(NSCalendarIdentifierISO8601)
it.populateFrom(dateTime)
it.timeZone = offset.toNSTimeZone()
}
}
/**
* Converts this date-time to an equivalent `NSDateComponents` object.
* @param includeCalendar `true` if the resulting `NSDateComponents` should include the ISO-8601 calendar
* @return an equivalent `NSDateComponents` object
*/
fun ZonedDateTime.toNSDateComponents(includeCalendar: Boolean = false): NSDateComponents {
return NSDateComponents().also {
if (includeCalendar) it.calendar = NSCalendar(NSCalendarIdentifierISO8601)
it.populateFrom(dateTime)
it.timeZone = zone.toNSTimeZone()
}
}
/**
* Converts this set of date components to an Island Time [Date].
*/
fun NSDateComponents.toIslandDate(): Date {
return Date(year.convert(), month.convert(), day.convert())
}
/**
* Converts this set of date components to an Island Time [Time].
*/
fun NSDateComponents.toIslandTime(): Time {
return Time(hour.convert(), minute.convert(), second.convert(), nanosecond.convert())
}
/**
* Converts this set of date components to an Island Time [DateTime].
*/
fun NSDateComponents.toIslandDateTime(): DateTime {
return DateTime(toIslandDate(), toIslandTime())
}
/**
* Converts this set of date components to an Island Time [OffsetDateTime].
* @throws DateTimeException if the `timeZone` property is absent.
*/
fun NSDateComponents.toIslandOffsetDateTime() = toIslandOffsetDateTimeOrNull()
?: throw DateTimeException("The 'timeZone' property must be non-null")
/**
* Converts this set of date components to an Island Time [OffsetDateTime], or `null` if the `timeZone` property is
* absent.
*/
fun NSDateComponents.toIslandOffsetDateTimeOrNull(): OffsetDateTime? {
return timeZone?.let {
val dateTime = toIslandDateTime()
OffsetDateTime(dateTime, it.toIslandTimeZone().rules.offsetAt(dateTime))
}
}
/**
* Converts this set of date components to an Island Time [ZonedDateTime].
* @throws DateTimeException if the `timeZone` property is absent.
*/
fun NSDateComponents.toIslandZonedDateTime() = toIslandZonedDateTimeOrNull()
?: throw DateTimeException("The 'timeZone' property must be non-null")
/**
* Converts this set of date components to an Island Time [ZonedDateTime], or `null` if the `timeZone` property is
* absent.
*/
fun NSDateComponents.toIslandZonedDateTimeOrNull(): ZonedDateTime? {
return timeZone?.let { ZonedDateTime(toIslandDateTime(), it.toIslandTimeZone()) }
}
/**
* Converts this time point to an `NSDate`.
*/
fun TimePoint.toNSDate(): NSDate {
return NSDate.dateWithTimeIntervalSince1970(
secondOfUnixEpoch.toDouble() + nanosecond.toDouble() / NANOSECONDS_PER_SECOND
)
}
/**
* Converts this `NSDate` to an Island Time [Instant].
*/
fun NSDate.toIslandInstant(): Instant {
val unixEpochSecond = timeIntervalSince1970.toLong()
val unixEpochNanoOfSecond = ((timeIntervalSince1970 - unixEpochSecond) * NANOSECONDS_PER_SECOND).toInt()
return Instant.fromSecondOfUnixEpoch(unixEpochSecond, unixEpochNanoOfSecond)
}
/**
* Converts this `NSDate` to an Island Time [DateTime] at the specified UTC offset.
*/
fun NSDate.toIslandDateTimeAt(offset: UtcOffset): DateTime {
val unixEpochSecond = timeIntervalSince1970.toLong()
val unixEpochNanoOfSecond = ((timeIntervalSince1970 - unixEpochSecond) * NANOSECONDS_PER_SECOND).toInt()
return DateTime.fromSecondOfUnixEpoch(unixEpochSecond, unixEpochNanoOfSecond, offset)
}
/**
* Converts this `NSDate` to an Island Time [DateTime] at the specified time zone.
*/
fun NSDate.toIslandDateTimeAt(nsTimeZone: NSTimeZone) = toIslandDateTimeAt(nsTimeZone.toIslandUtcOffsetAt(this))
/**
* Converts this `NSDate` to an Island Time [OffsetDateTime] at the specified [offset].
*/
fun NSDate.toIslandOffsetDateTimeAt(offset: UtcOffset): OffsetDateTime {
val unixEpochSecond = timeIntervalSince1970.toLong()
val unixEpochNanoOfSecond = ((timeIntervalSince1970 - unixEpochSecond) * NANOSECONDS_PER_SECOND).toInt()
return OffsetDateTime.fromSecondOfUnixEpoch(unixEpochSecond, unixEpochNanoOfSecond, offset)
}
/**
* Converts this `NSDate` to an Island Time [OffsetDateTime] at the specified time zone.
*/
fun NSDate.toIslandOffsetDateTimeAt(nsTimeZone: NSTimeZone): OffsetDateTime {
return toIslandOffsetDateTimeAt(nsTimeZone.toIslandUtcOffsetAt(this))
}
/**
* Converts this `NSDate` to an Island Time [ZonedDateTime] at the specified time zone.
*/
fun NSDate.toIslandZonedDateTimeAt(zone: TimeZone): ZonedDateTime {
val unixEpochSecond = timeIntervalSince1970.toLong()
val unixEpochNanoOfSecond = ((timeIntervalSince1970 - unixEpochSecond) * NANOSECONDS_PER_SECOND).toInt()
return ZonedDateTime.fromSecondOfUnixEpoch(unixEpochSecond, unixEpochNanoOfSecond, zone)
}
/**
* Converts this `NSDate` to an Island Time [ZonedDateTime] at the specified time zone.
*/
fun NSDate.toIslandZonedDateTimeAt(nsTimeZone: NSTimeZone) = toIslandZonedDateTimeAt(nsTimeZone.toIslandTimeZone())
/**
* Converts this offset into an equivalent `NSTimeZone` with a fixed UTC offset.
*
* Note that `NSTimeZone`will round the `totalSeconds` value to the nearest minute.
*/
fun UtcOffset.toNSTimeZone(): NSTimeZone = NSTimeZone.timeZoneForSecondsFromGMT(totalSeconds.value.convert())
@Deprecated(
message = "This operation is ambiguous. An NSDate must be provided.",
replaceWith = ReplaceWith("this.toIslandUtcOffsetAt()"),
level = DeprecationLevel.ERROR
)
fun NSTimeZone.toIslandUtcOffset(): UtcOffset = throw UnsupportedOperationException("Should not be called")
/**
* Converts this `NSTimeZone` to an Island Time [UtcOffset] at the provided date.
*/
fun NSTimeZone.toIslandUtcOffsetAt(date: NSDate): UtcOffset {
return secondsFromGMTForDate(date).convert().seconds.asUtcOffset()
}
/**
* Converts this NSTimeZone` to an Island Time [TimeZone] with the same identifier.
*/
fun NSTimeZone.toIslandTimeZone(): TimeZone = TimeZone(name)
/**
* Converts this time zone to an `NSTimeZone`.
* @throws TimeZoneRulesException if the identifier isn't recognized as valid for an `NSTimeZone`
*/
fun TimeZone.toNSTimeZone(): NSTimeZone = toNSTimeZoneOrNull()
?: throw TimeZoneRulesException("The identifier '$id' could not be converted to an NSTimeZone")
/**
* Converts this time zone to an `NSTimeZone`, or `null` if the identifier isn't recognized as valid for an
* `NSTimeZone`.
*/
fun TimeZone.toNSTimeZoneOrNull(): NSTimeZone? {
return if (this is TimeZone.FixedOffset) {
NSTimeZone.timeZoneForSecondsFromGMT(offset.totalSeconds.value.convert())
} else {
NSTimeZone.timeZoneWithName(id)
}
}
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun Duration.toNSTimeInterval(): NSTimeInterval = toComponents { seconds, nanoseconds ->
seconds.value.toDouble() + nanoseconds.value.toDouble() / NANOSECONDS_PER_SECOND
}
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun IntDays.toNSTimeInterval(): NSTimeInterval = this.toLongDays().inSecondsUnchecked.value.toDouble()
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun LongDays.toNSTimeInterval(): NSTimeInterval = this.inSeconds.value.toDouble()
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun IntHours.toNSTimeInterval(): NSTimeInterval = this.toLongHours().inSecondsUnchecked.value.toDouble()
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun LongHours.toNSTimeInterval(): NSTimeInterval = this.inSeconds.value.toDouble()
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun IntMinutes.toNSTimeInterval(): NSTimeInterval = this.toLongMinutes().inSecondsUnchecked.value.toDouble()
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun LongMinutes.toNSTimeInterval(): NSTimeInterval = this.inSeconds.value.toDouble()
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun IntSeconds.toNSTimeInterval(): NSTimeInterval = value.toDouble()
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun LongSeconds.toNSTimeInterval(): NSTimeInterval = value.toDouble()
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun IntMilliseconds.toNSTimeInterval(): NSTimeInterval = toComponents { seconds, milliseconds ->
seconds.value.toDouble() + milliseconds.value.toDouble() / MILLISECONDS_PER_SECOND
}
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun LongMilliseconds.toNSTimeInterval(): NSTimeInterval = toComponents { seconds, milliseconds ->
seconds.value.toDouble() + milliseconds.value.toDouble() / MILLISECONDS_PER_SECOND
}
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun IntMicroseconds.toNSTimeInterval(): NSTimeInterval = toComponents { seconds, microseconds ->
seconds.value.toDouble() + microseconds.value.toDouble() / MICROSECONDS_PER_SECOND
}
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun LongMicroseconds.toNSTimeInterval(): NSTimeInterval = toComponents { seconds, microseconds ->
seconds.value.toDouble() + microseconds.value.toDouble() / MICROSECONDS_PER_SECOND
}
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun IntNanoseconds.toNSTimeInterval(): NSTimeInterval = toComponents { seconds, nanoseconds ->
seconds.value.toDouble() + nanoseconds.value.toDouble() / NANOSECONDS_PER_SECOND
}
/**
* Converts this duration to an equivalent `NSTimeInterval`.
*/
fun LongNanoseconds.toNSTimeInterval(): NSTimeInterval = toComponents { seconds, nanoseconds ->
seconds.value.toDouble() + nanoseconds.value.toDouble() / NANOSECONDS_PER_SECOND
}
/**
* Converts this interval to an equivalent `NSDateInterval`.
* @throws UnsupportedOperationException if the interval is unbounded
*/
fun > TimePointInterval.toNSDateInterval(): NSDateInterval {
return toNSDateIntervalOrNull()
?: throw UnsupportedOperationException("An unbounded interval cannot be converted to an NSDateInterval")
}
/**
* Converts this interval to an equivalent `NSDateInterval`, or `null` if the interval is unbounded.
*/
fun > TimePointInterval.toNSDateIntervalOrNull(): NSDateInterval? {
return if (isBounded()) {
NSDateInterval(start.toNSDate(), endExclusive.toNSDate())
} else {
null
}
}
/**
* Converts this interval to an equivalent Island Time [InstantInterval].
*/
fun NSDateInterval.toIslandInstantInterval(): InstantInterval {
return startDate.toIslandInstant() until endDate.toIslandInstant()
}
private fun NSDateComponents.populateFrom(date: Date) {
year = date.year.convert()
month = date.monthNumber.convert()
day = date.dayOfMonth.convert()
}
private fun NSDateComponents.populateFrom(time: Time) {
hour = time.hour.convert()
minute = time.minute.convert()
second = time.second.convert()
nanosecond = time.nanosecond.convert()
}
private fun NSDateComponents.populateFrom(dateTime: DateTime) {
populateFrom(dateTime.date)
populateFrom(dateTime.time)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy