Skip to content

Commit

Permalink
use DateTimeFormatter to format dates on Android and cache it for the…
Browse files Browse the repository at this point in the history
… current Locale.
  • Loading branch information
cbeyls committed May 26, 2024
1 parent 53fe3a9 commit 0a3b1db
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 32 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
Original file line number Diff line number Diff line change
@@ -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<K, V>(private val factory: (K) -> V) {
private val cache = AtomicReference<Pair<K, V>?>(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 {
Expand Down

0 comments on commit 0a3b1db

Please sign in to comment.