Skip to content

Commit

Permalink
Add methods to access week-related properties directly using Locale (#…
Browse files Browse the repository at this point in the history
…110)

* Add methods to access week-related properties directly using Locale

* Fix Darwin build
  • Loading branch information
erikc5000 committed Jul 26, 2020
1 parent c0f7e60 commit 1b7d1d9
Show file tree
Hide file tree
Showing 9 changed files with 436 additions and 81 deletions.
285 changes: 241 additions & 44 deletions core/src/commonMain/generated/io/islandtime/_DateProperties.kt

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions core/src/commonMain/kotlin/io/islandtime/WeekDate.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
package io.islandtime

import io.islandtime.calendar.WeekSettings
import io.islandtime.calendar.weekSettings
import io.islandtime.internal.lastWeekOfWeekBasedYear
import io.islandtime.locale.Locale
import io.islandtime.measures.days
import io.islandtime.measures.weeks
import kotlin.jvm.JvmMultifileClass
Expand All @@ -24,6 +26,16 @@ inline fun <T> Date.toWeekDate(settings: WeekSettings, action: (year: Int, week:
return action(weekBasedYear(settings), weekOfWeekBasedYear(settings), dayOfWeek.number(settings))
}

/**
* Converts this date to a week date representation using the week definition associated with the provided [locale].
*
* Keep in mind that that the system's calendar settings may differ from that of the default locale on some platforms.
* To respect the system calendar settings, use [WeekSettings.systemDefault] instead.
*/
inline fun <T> Date.toWeekDate(locale: Locale, action: (year: Int, week: Int, day: Int) -> T): T {
return toWeekDate(locale.weekSettings, action)
}

/**
* Create a [Date] from an ISO week date.
* @param year the week-based year
Expand Down Expand Up @@ -77,6 +89,17 @@ fun Date.Companion.fromWeekDate(year: Int, week: Int, day: Int, settings: WeekSe
return date + daysToAdd
}

/**
* Create a [Date] from a week date representation using the week definition associated with the provided [locale].
* @param year the week-based year
* @param week the week number of the week-based year
* @param day the day of week number, 1-7
* @param locale the locale providing the week definition to use when interpreting the [year], [week], and [day]
*/
fun Date.Companion.fromWeekDate(year: Int, week: Int, day: Int, locale: Locale): Date {
return fromWeekDate(year, week, day, locale.weekSettings)
}

private fun checkValidWeekOfWeekBasedYear(week: Int): Int {
if (week !in 1..53) {
throw DateTimeException("The week '$week' is outside the supported range of 1-53")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ data class WeekSettings(

companion object {
/**
* The definition of a week according to the current system settings. This may differ from the definition
* associated with the default locale on platforms that allow this to be customized, such as iOS and macOS.
* Returns the definition of a week according to the current system settings. This may differ from the
* definition associated with the default locale on platforms that allow this to be customized, such as iOS and
* macOS.
*/
fun systemDefault(): WeekSettings = systemDefaultWeekSettings()

Expand All @@ -36,5 +37,10 @@ data class WeekSettings(
}
}

/**
* The default [WeekSettings] associated with this locale.
*/
expect val Locale.weekSettings: WeekSettings

internal expect fun systemDefaultWeekSettings(): WeekSettings
internal expect val Locale.firstDayOfWeek: DayOfWeek
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@ import io.islandtime.measures.IntWeeks
import io.islandtime.measures.weeks
import io.islandtime.measures.years

internal inline val Date.weekOfMonthImpl: Int get() = weekOfMonthImpl(WeekSettings.ISO)
internal inline fun Date.weekOfMonthImpl(settings: WeekSettings): Int = weekNumber(dayOfMonth, settings)
internal inline val Date.weekOfYearImpl: Int get() = weekOfYearImpl(WeekSettings.ISO)
internal inline fun Date.weekOfYearImpl(settings: WeekSettings): Int = weekNumber(dayOfYear, settings)
internal inline val Date.weekBasedYearImpl: Int get() = weekBasedYearImpl(WeekSettings.ISO)

internal inline fun Date.weekBasedYearImpl(settings: WeekSettings): Int {
internal fun Date.weekBasedYearImpl(settings: WeekSettings): Int {
val dayOfYear = dayOfYear
val offset = startOfWeekOffset(dayOfWeek, dayOfYear, settings)
val week = weekNumber(dayOfYear, offset)
Expand All @@ -31,9 +28,7 @@ internal inline fun Date.weekBasedYearImpl(settings: WeekSettings): Int {
}
}

internal inline val Date.weekOfWeekBasedYearImpl: Int get() = weekOfWeekBasedYearImpl(WeekSettings.ISO)

internal inline fun Date.weekOfWeekBasedYearImpl(settings: WeekSettings): Int {
internal fun Date.weekOfWeekBasedYearImpl(settings: WeekSettings): Int {
val dayOfYear = dayOfYear
val offset = startOfWeekOffset(dayOfWeek, dayOfYear, settings)
val week = weekNumber(dayOfYear, offset)
Expand Down
14 changes: 11 additions & 3 deletions core/src/commonTest/kotlin/io/islandtime/DatePropertiesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ class DatePropertiesTest : AbstractIslandTimeTest() {
Date(2009, 1, 4) to 2,
Date(2020, 5, 31) to 6
).forEach { (date, week) ->
assertEquals(week, date.weekOfMonth(SUNDAY_START), date.toString())
assertEquals(week, date.weekOfMonth(SUNDAY_START), message = "$date (SUNDAY_START)")
assertEquals(week, date.weekOfMonth(en_US), message = "$date (en-US)")
}
}

Expand Down Expand Up @@ -168,7 +169,8 @@ class DatePropertiesTest : AbstractIslandTimeTest() {
Date(2009, 1, 3) to 1,
Date(2009, 1, 4) to 2
).forEach { (date, week) ->
assertEquals(week, date.weekOfYear(SUNDAY_START), date.toString())
assertEquals(week, date.weekOfYear(SUNDAY_START), message = "$date (SUNDAY_START)")
assertEquals(week, date.weekOfYear(en_US), message = "$date (en-US)")
}
}

Expand Down Expand Up @@ -211,7 +213,13 @@ class DatePropertiesTest : AbstractIslandTimeTest() {
assertEquals(
Pair(year, week),
Pair(date.weekBasedYear(SUNDAY_START), date.weekOfWeekBasedYear(SUNDAY_START)),
date.toString()
message = "$date (SUNDAY_START)"
)

assertEquals(
Pair(year, week),
Pair(date.weekBasedYear(en_US), date.weekOfWeekBasedYear(en_US)),
message = "$date (en-US)"
)
}
}
Expand Down
10 changes: 8 additions & 2 deletions core/src/commonTest/kotlin/io/islandtime/WeekDateTest.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package io.islandtime

import io.islandtime.calendar.WeekSettings.Companion.SUNDAY_START
import io.islandtime.locale.localeOf
import io.islandtime.test.AbstractIslandTimeTest
import io.islandtime.test.TestData
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith

class WeekDateTest : AbstractIslandTimeTest() {
@Suppress("PrivatePropertyName")
private val en_US = localeOf("en-US")

@Test
fun `Date_toWeekDate() converts to ISO week date`() {
TestData.isoWeekDates.forEach { (date, weekDate) ->
Expand All @@ -18,7 +22,8 @@ class WeekDateTest : AbstractIslandTimeTest() {
@Test
fun `Date_toWeekDate() converts to week date with Sunday start week definition`() {
TestData.sundayStartWeekDates.forEach { (date, weekDate) ->
assertEquals(weekDate, date.toWeekDate(SUNDAY_START, ::Triple), date.toString())
assertEquals(weekDate, date.toWeekDate(SUNDAY_START, ::Triple), message = "$date (SUNDAY_START)")
assertEquals(weekDate, date.toWeekDate(en_US, ::Triple), message = "$date (en-US)")
}
}

Expand Down Expand Up @@ -75,7 +80,8 @@ class WeekDateTest : AbstractIslandTimeTest() {
fun `Date_fromWeekDate() creates a Date from a Sunday start week date`() {
TestData.sundayStartWeekDates.filter { it.first != Date.MAX }.forEach { (date, weekDate) ->
val (year, week, day) = weekDate
assertEquals(date, Date.fromWeekDate(year, week, day, SUNDAY_START), date.toString())
assertEquals(date, Date.fromWeekDate(year, week, day, SUNDAY_START), message = "$date (SUNDAY_START)")
assertEquals(date, Date.fromWeekDate(year, week, day, en_US), message = "$date (en-US)")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ import kotlinx.cinterop.convert
import platform.Foundation.NSCalendar
import platform.Foundation.NSCalendarIdentifierGregorian

actual val Locale.weekSettings: WeekSettings
get() = NSCalendar(NSCalendarIdentifierGregorian)
.also { it.locale = this }
.run { WeekSettings(firstDayOfWeek, minimumDaysInFirstWeek.convert()) }

internal actual fun systemDefaultWeekSettings(): WeekSettings {
return with(NSCalendar.currentCalendar) {
WeekSettings(firstDayOfWeek, minimumDaysInFirstWeek().convert())
}
return with(NSCalendar.currentCalendar) { WeekSettings(firstDayOfWeek, minimumDaysInFirstWeek.convert()) }
}

internal actual val Locale.firstDayOfWeek: DayOfWeek
Expand Down
12 changes: 6 additions & 6 deletions core/src/jvmMain/kotlin/io/islandtime/calendar/WeekSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import io.islandtime.locale.Locale
import io.islandtime.measures.days
import java.util.*

internal actual fun systemDefaultWeekSettings(): WeekSettings {
val gregorianCalendar = GregorianCalendar(Locale.getDefault().withoutVariant())

return with(gregorianCalendar) {
WeekSettings(firstIslandDayOfWeek, minimalDaysInFirstWeek)
actual val Locale.weekSettings: WeekSettings
get() {
val gregorianCalendar = GregorianCalendar(this.withoutVariant())
return with(gregorianCalendar) { WeekSettings(firstIslandDayOfWeek, minimalDaysInFirstWeek) }
}
}

internal actual fun systemDefaultWeekSettings(): WeekSettings = Locale.getDefault().weekSettings

internal actual val Locale.firstDayOfWeek: DayOfWeek
get() = GregorianCalendar(this.withoutVariant()).firstIslandDayOfWeek
Expand Down
Loading

0 comments on commit 1b7d1d9

Please sign in to comment.