From 230923fe008e5d74a46eb6e483e16f2223657756 Mon Sep 17 00:00:00 2001 From: Alexander Zhirkevich Date: Fri, 15 Mar 2024 15:56:13 +0300 Subject: [PATCH] Locale-aware date formatting for desktop (#1159) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not a complete solution - just localization for default m3 skeletons. User-provided variants will still be ugly :( Before and after: Снимок экрана 2024-02-29 в 21 17 28 Screenshot 2024-03-04 at 17 22 51 --- .../material3/PlatformDateFormat.desktop.kt | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/PlatformDateFormat.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/PlatformDateFormat.desktop.kt index 94ce9b959d313..8698011064990 100644 --- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/PlatformDateFormat.desktop.kt +++ b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/PlatformDateFormat.desktop.kt @@ -19,9 +19,14 @@ package androidx.compose.material3 import java.text.DateFormat import java.text.SimpleDateFormat import java.time.DayOfWeek +import java.time.Instant +import java.time.ZoneOffset +import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle import java.time.format.TextStyle +@OptIn(ExperimentalMaterial3Api::class) internal actual class PlatformDateFormat actual constructor(private val locale: CalendarLocale) { private val delegate = LegacyCalendarModelImpl(locale) @@ -40,18 +45,26 @@ internal actual class PlatformDateFormat actual constructor(private val locale: skeleton: String ): String { // Note: there is no equivalent in Java for Android's DateFormat.getBestDateTimePattern. - // The JDK SimpleDateFormat expects a pattern, so the results will be "2023Jan7", + // The JDK SimpleDateFormat expects a pattern, so the results for unrecognized skeletons will be "2023Jan7", // "2023January", etc. in case a skeleton holds an actual ICU skeleton and not a pattern. // TODO: support ICU skeleton on JVM // Maybe it will be supported in kotlinx.datetime in the future. - // See https://github.com/Kotlin/kotlinx-datetime/pull/251 - // stub: not localized but at least readable variant val pattern = when(skeleton){ - DatePickerDefaults.YearMonthSkeleton -> "MMMM yyyy" - DatePickerDefaults.YearAbbrMonthDaySkeleton -> "MMM d, yyyy" - DatePickerDefaults.YearMonthWeekdayDaySkeleton -> "EEEE, MMMM d, yyyy" + DatePickerDefaults.YearAbbrMonthDaySkeleton -> { + return DateTimeFormatter + .ofLocalizedDate(FormatStyle.MEDIUM) + .localizedBy(locale) + .format(Instant.ofEpochMilli(utcTimeMillis).atOffset(ZoneOffset.UTC)) + } + DatePickerDefaults.YearMonthWeekdayDaySkeleton -> { + return DateTimeFormatter + .ofLocalizedDate(FormatStyle.FULL) + .localizedBy(locale) + .format(Instant.ofEpochMilli(utcTimeMillis).atOffset(ZoneOffset.UTC)) + } + DatePickerDefaults.YearMonthSkeleton -> "LLLL yyyy" // L is a pattern for standalone month (without day) else -> skeleton } return formatWithPattern(utcTimeMillis, pattern)