From 91aa6f4efc294143629446a277d4a47a5623a2bb Mon Sep 17 00:00:00 2001 From: Guzinowich Date: Fri, 31 Jul 2026 20:19:45 +0300 Subject: [PATCH 1/2] fix: localize app status and backup timestamps --- app/src/main/java/to/bitkit/ext/DateTime.kt | 5 ++- .../java/to/bitkit/ext/DateTimeExtTest.kt | 38 +++++++++++++++++++ changelog.d/next/1112.fixed.md | 1 + 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 changelog.d/next/1112.fixed.md diff --git a/app/src/main/java/to/bitkit/ext/DateTime.kt b/app/src/main/java/to/bitkit/ext/DateTime.kt index 69c94349d..8358e3871 100644 --- a/app/src/main/java/to/bitkit/ext/DateTime.kt +++ b/app/src/main/java/to/bitkit/ext/DateTime.kt @@ -29,6 +29,7 @@ import kotlin.time.Clock import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.milliseconds import kotlin.time.ExperimentalTime +import java.text.DateFormat as JavaDateFormat import java.time.LocalDate as JavaLocalDate import kotlin.time.Instant as KInstant @@ -68,10 +69,10 @@ fun Long.toDateUTC(): String { return dateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) } -fun Long.toLocalizedTimestamp(locale: Locale = Locale.US): String { +fun Long.toLocalizedTimestamp(locale: Locale = Locale.getDefault()): String { val date = Date(this) val formatter = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT, ULocale.forLocale(locale)) - ?: return SimpleDateFormat("MMMM d, yyyy 'at' h:mm a", locale).format(date) + ?: return JavaDateFormat.getDateTimeInstance(JavaDateFormat.LONG, JavaDateFormat.SHORT, locale).format(date) return formatter.format(date) } diff --git a/app/src/test/java/to/bitkit/ext/DateTimeExtTest.kt b/app/src/test/java/to/bitkit/ext/DateTimeExtTest.kt index 5332e7091..cc2195098 100644 --- a/app/src/test/java/to/bitkit/ext/DateTimeExtTest.kt +++ b/app/src/test/java/to/bitkit/ext/DateTimeExtTest.kt @@ -20,6 +20,9 @@ class DateTimeExtTest : BaseUnitTest() { val AFTERNOON: Instant = Instant.parse("2026-03-07T15:23:00Z") val MIDNIGHT: Instant = Instant.parse("2026-03-07T00:15:00Z") val NOON: Instant = Instant.parse("2026-03-07T12:05:00Z") + + // Midday so the calendar day, and with it the month name, holds in every time zone + val MIDDAY_IN_JULY: Long = Instant.parse("2026-07-27T12:00:00Z").toEpochMilli() } @Test @@ -261,5 +264,40 @@ class DateTimeExtTest : BaseUnitTest() { assertEquals(UiDateStyle.DATE_TIME, uiDateStyleFor(lateEvening.epochSecond.toULong(), today, bucharest)) } + @Test + fun `toLocalizedTimestamp uses the supplied locale`() { + val inGerman = MIDDAY_IN_JULY.toLocalizedTimestamp(Locale.GERMANY) + val inUs = MIDDAY_IN_JULY.toLocalizedTimestamp(Locale.US) + + assertTrue(inGerman.contains("Juli"), "expected a German month name, got '$inGerman'") + assertTrue(inUs.contains("July"), "expected an English month name, got '$inUs'") + } + + @Test + fun `toLocalizedTimestamp follows the default locale when none is supplied`() { + val original = Locale.getDefault() + try { + Locale.setDefault(Locale.GERMANY) + val result = MIDDAY_IN_JULY.toLocalizedTimestamp() + + assertTrue(result.contains("Juli"), "expected a German month name, got '$result'") + } finally { + Locale.setDefault(original) + } + } + + @Test + fun `toLocalizedTimestamp orders the date the way the locale does`() { + val original = Locale.getDefault() + try { + Locale.setDefault(Locale.GERMANY) + val result = MIDDAY_IN_JULY.toLocalizedTimestamp() + + assertTrue(result.indexOf("27") < result.indexOf("Juli"), "expected day before month, got '$result'") + } finally { + Locale.setDefault(original) + } + } + private fun Instant.formattedInUtc(pattern: String) = formatted(pattern, Locale.US, UTC) } diff --git a/changelog.d/next/1112.fixed.md b/changelog.d/next/1112.fixed.md new file mode 100644 index 000000000..d5b925dd7 --- /dev/null +++ b/changelog.d/next/1112.fixed.md @@ -0,0 +1 @@ +App Status and Backup timestamps now follow the device language instead of always using the US date format. From 6b6ed418c4555f0b8cd78ca740d0119e1bf6bbf1 Mon Sep 17 00:00:00 2001 From: Guzinowich Date: Fri, 31 Jul 2026 20:21:39 +0300 Subject: [PATCH 2/2] chore: rename changelog fragment --- changelog.d/next/{1112.fixed.md => 1124.fixed.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog.d/next/{1112.fixed.md => 1124.fixed.md} (100%) diff --git a/changelog.d/next/1112.fixed.md b/changelog.d/next/1124.fixed.md similarity index 100% rename from changelog.d/next/1112.fixed.md rename to changelog.d/next/1124.fixed.md