diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 594808f3..47e9e5c0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -58,7 +58,7 @@ kotlin-plugin-compose = { group = "org.jetbrains.kotlin", name = "compose-compil kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" } kotlinx-coroutines-play-services = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services", version.ref = "coroutines" } -kotlinx-datetime = "org.jetbrains.kotlinx:kotlinx-datetime:0.5.0" +kotlinx-datetime = "org.jetbrains.kotlinx:kotlinx-datetime:0.6.0" openfeedback-m3 = "io.openfeedback:openfeedback-m3:0.2.3" play-services-auth = "com.google.android.gms:play-services-auth:21.1.0" moko-resources = { module = "dev.icerock.moko:resources", version.ref = "moko" } diff --git a/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/utils/DateUtils.android.kt b/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/utils/DateUtils.android.kt index 53867ebb..320a1661 100644 --- a/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/utils/DateUtils.android.kt +++ b/shared/domain/src/androidMain/kotlin/fr/androidmakers/domain/utils/DateUtils.android.kt @@ -1,52 +1,59 @@ +@file:SuppressLint("NewApi") + package fr.androidmakers.domain.utils -import android.text.format.DateUtils +import android.annotation.SuppressLint import kotlinx.datetime.Instant import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDateTime -import kotlinx.datetime.atStartOfDayIn -import kotlinx.datetime.toInstant -import kotlinx.datetime.toJavaLocalDateTime -import java.text.DateFormat.MEDIUM -import java.text.DateFormat.SHORT -import java.text.SimpleDateFormat +import kotlinx.datetime.toJavaLocalDate +import kotlinx.datetime.toJavaLocalTime +import kotlinx.datetime.toLocalDateTime import java.time.format.DateTimeFormatter import java.time.format.FormatStyle -import java.util.Date import java.util.Locale -import java.util.TimeZone +import java.util.concurrent.atomic.AtomicReference + +/** + * Lazily compute a value from the given key and cache it until the key changes. + */ +private class KeyValueCache(private val factory: (K) -> V) { + private val cache = AtomicReference?>(null) + + fun get(key: K): V { + val currentPair = cache.get() + if (currentPair != null && currentPair.first == key) { + return currentPair.second + } + val newPair = key to factory(key) + // Only update the cache if it didn't change in the meantime + cache.compareAndSet(currentPair, newPair) + return newPair.second + } +} + +private val shortTimeFormatterCache = KeyValueCache { locale: Locale -> + DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).withLocale(locale) +} + +private val mediumDateFormatterCache = KeyValueCache { locale: Locale -> + DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(locale) +} actual fun LocalDateTime.formatShortTime(): String { - return this.toInstant(kotlinx.datetime.TimeZone.currentSystemDefault()).formatShortTime() + val shortTimeFormatter = shortTimeFormatterCache.get(Locale.getDefault()) + return time.toJavaLocalTime().format(shortTimeFormatter).lowercase(Locale.getDefault()) } actual fun Instant.formatShortTime(): String { - val dateFormat = SimpleDateFormat.getTimeInstance(SHORT) - // Display the time in the local time as everyone will be on site so it makes // planning in advance easier - val tz = TimeZone.getTimeZone("Europe/Paris") - if (tz != null) { - dateFormat.timeZone = tz - } - - val date = Date(this.toEpochMilliseconds()) - return dateFormat.format(date).lowercase(Locale.getDefault()) + return toLocalDateTime(eventTimeZone).formatShortTime() } actual fun LocalDate.formatMediumDate(): String { - val dateFormat = SimpleDateFormat.getDateInstance(MEDIUM) - - val tz = TimeZone.getTimeZone("Europe/Paris") - if (tz != null) { - dateFormat.timeZone = tz - } - - val date = Date( - this.atStartOfDayIn(kotlinx.datetime.TimeZone.currentSystemDefault()) - .toEpochMilliseconds() - ) - return dateFormat.format(date).lowercase(Locale.getDefault()) + val mediumDateFormatter = mediumDateFormatterCache.get(Locale.getDefault()) + return toJavaLocalDate().format(mediumDateFormatter).lowercase(Locale.getDefault()) } actual fun formatTimeInterval(startDate: LocalDateTime, endDate: LocalDateTime): String {