From 94cb850fa4ed67b76c2d90657864c2a7b3a5cb01 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Wed, 23 Sep 2026 18:15:12 +0200 Subject: [PATCH] core-time: optional 12/24-hour override for formatTime and friends --- .../floret/time/DateTimeFormat.kt | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/core-time/src/main/kotlin/de/jeanlucmakiola/floret/time/DateTimeFormat.kt b/core-time/src/main/kotlin/de/jeanlucmakiola/floret/time/DateTimeFormat.kt index bb5367a..d7f2208 100644 --- a/core-time/src/main/kotlin/de/jeanlucmakiola/floret/time/DateTimeFormat.kt +++ b/core-time/src/main/kotlin/de/jeanlucmakiola/floret/time/DateTimeFormat.kt @@ -39,12 +39,25 @@ private fun Instant.atDisplayZone(allDay: Boolean) = fun Instant.formatDate(allDay: Boolean = false): String = atDisplayZone(allDay).format(dateFormatter) -/** Short localized time, e.g. "14:30". */ -fun Instant.formatTime(): String = atSystemZone().format(timeFormatter) +private val timeFormatter24: DateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm") +private val timeFormatter12: DateTimeFormatter = DateTimeFormatter.ofPattern("h:mm a") + +/** + * Short time, e.g. "14:30". [is24Hour] forces a 12- or 24-hour clock; null keeps + * the locale's own short pattern. + */ +fun Instant.formatTime(is24Hour: Boolean? = null): String { + val formatter = when (is24Hour) { + null -> timeFormatter + true -> timeFormatter24 + false -> timeFormatter12.withLocale(Locale.getDefault()) + } + return atSystemZone().format(formatter) +} /** Date alone for all-day items, otherwise date + time. */ -fun Instant.formatDateTime(allDay: Boolean): String = - if (allDay) formatDate(allDay = true) else "${formatDate()} · ${formatTime()}" +fun Instant.formatDateTime(allDay: Boolean, is24Hour: Boolean? = null): String = + if (allDay) formatDate(allDay = true) else "${formatDate()} · ${formatTime(is24Hour)}" // The locale's medium date pattern with the year token stripped, e.g. "20 Jun" / // "Jun 20" — derived from the pattern so day/month order still follows the locale. @@ -62,11 +75,11 @@ private val dateNoYearFormatter: DateTimeFormatter = run { * current year, and the time is dropped when it carries no information (all-day * items, or a midnight time). Examples: "20 Jun", "20 Jun · 14:30", "20 Jun 2027". */ -fun Instant.formatDateTimeCompact(allDay: Boolean): String { +fun Instant.formatDateTimeCompact(allDay: Boolean, is24Hour: Boolean? = null): String { val zdt = atDisplayZone(allDay) val datePart = if (zdt.year == LocalDate.now(ZoneId.systemDefault()).year) zdt.format(dateNoYearFormatter) else formatDate(allDay) return if (allDay || zdt.toLocalTime() == LocalTime.MIDNIGHT) datePart - else "$datePart · ${formatTime()}" + else "$datePart · ${formatTime(is24Hour)}" }