diff --git a/changelog.d/2916.misc b/changelog.d/2916.misc new file mode 100644 index 0000000000..b87146dd58 --- /dev/null +++ b/changelog.d/2916.misc @@ -0,0 +1 @@ +Use a more natural date format for day dividers in the timeline. Also improve the time format for last messages in the room list. diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt index 9493079925..5d92f137e5 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt @@ -26,19 +26,18 @@ import kotlinx.datetime.toJavaLocalDate import kotlinx.datetime.toJavaLocalDateTime import java.time.Period import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle import java.util.Locale import javax.inject.Inject import kotlin.math.absoluteValue -// TODO rework this date formatting class DateFormatters @Inject constructor( private val locale: Locale, private val clock: Clock, private val timeZone: TimeZone, ) { private val onlyTimeFormatter: DateTimeFormatter by lazy { - val pattern = DateFormat.getBestDateTimePattern(locale, "HH:mm") ?: "HH:mm" - DateTimeFormatter.ofPattern(pattern, locale) + DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).withLocale(locale) } private val dateWithMonthFormatter: DateTimeFormatter by lazy { @@ -51,6 +50,10 @@ class DateFormatters @Inject constructor( DateTimeFormatter.ofPattern(pattern, locale) } + private val dateWithFullFormatFormatter: DateTimeFormatter by lazy { + DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(locale) + } + internal fun formatTime(localDateTime: LocalDateTime): String { return onlyTimeFormatter.format(localDateTime.toJavaLocalDateTime()) } @@ -63,6 +66,10 @@ class DateFormatters @Inject constructor( return dateWithYearFormatter.format(localDateTime.toJavaLocalDateTime()) } + internal fun formatDateWithFullFormat(localDateTime: LocalDateTime): String { + return dateWithFullFormatFormatter.format(localDateTime.toJavaLocalDateTime()) + } + internal fun formatDate( dateToFormat: LocalDateTime, currentDate: LocalDateTime, diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDaySeparatorFormatter.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDaySeparatorFormatter.kt index 90d7f5c205..2760894645 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDaySeparatorFormatter.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDaySeparatorFormatter.kt @@ -28,6 +28,7 @@ class DefaultDaySeparatorFormatter @Inject constructor( ) : DaySeparatorFormatter { override fun format(timestamp: Long): String { val dateToFormat = localDateTimeProvider.providesFromTimestamp(timestamp) - return dateFormatters.formatDateWithYear(dateToFormat) + // TODO use relative formatting once iOS uses it too + return dateFormatters.formatDateWithFullFormat(dateToFormat) } } diff --git a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultLastMessageTimestampFormatterTest.kt b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultLastMessageTimestampFormatterTest.kt index dd8f75cae3..38e4fbffb3 100644 --- a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultLastMessageTimestampFormatterTest.kt +++ b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultLastMessageTimestampFormatterTest.kt @@ -21,6 +21,7 @@ import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormat import io.element.android.libraries.dateformatter.test.FakeClock import kotlinx.datetime.Instant import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime import org.junit.Test import java.util.Locale @@ -44,7 +45,7 @@ class DefaultLastMessageTimestampFormatterTest { val now = "1980-04-06T18:35:24.00Z" val dat = "1980-04-06T18:35:24.00Z" val formatter = createFormatter(now) - assertThat(formatter.format(Instant.parse(dat).toEpochMilliseconds())).isEqualTo("18:35") + assertThat(formatter.format(Instant.parse(dat).toEpochMilliseconds())).isEqualTo("6:35 PM") } @Test @@ -52,7 +53,7 @@ class DefaultLastMessageTimestampFormatterTest { val now = "1980-04-06T18:35:24.00Z" val dat = "1980-04-06T18:35:23.00Z" val formatter = createFormatter(now) - assertThat(formatter.format(Instant.parse(dat).toEpochMilliseconds())).isEqualTo("18:35") + assertThat(formatter.format(Instant.parse(dat).toEpochMilliseconds())).isEqualTo("6:35 PM") } @Test @@ -60,7 +61,7 @@ class DefaultLastMessageTimestampFormatterTest { val now = "1980-04-06T18:35:24.00Z" val dat = "1980-04-06T18:34:24.00Z" val formatter = createFormatter(now) - assertThat(formatter.format(Instant.parse(dat).toEpochMilliseconds())).isEqualTo("18:34") + assertThat(formatter.format(Instant.parse(dat).toEpochMilliseconds())).isEqualTo("6:34 PM") } @Test @@ -68,7 +69,7 @@ class DefaultLastMessageTimestampFormatterTest { val now = "1980-04-06T18:35:24.00Z" val dat = "1980-04-06T17:35:24.00Z" val formatter = createFormatter(now) - assertThat(formatter.format(Instant.parse(dat).toEpochMilliseconds())).isEqualTo("17:35") + assertThat(formatter.format(Instant.parse(dat).toEpochMilliseconds())).isEqualTo("5:35 PM") } @Test @@ -96,6 +97,15 @@ class DefaultLastMessageTimestampFormatterTest { assertThat(formatter.format(Instant.parse(dat).toEpochMilliseconds())).isEqualTo("06.04.1979") } + @Test + fun `test full format`() { + val now = "1980-04-06T18:35:24.00Z" + val dat = "1979-04-06T18:35:24.00Z" + val clock = FakeClock().apply { givenInstant(Instant.parse(now)) } + val dateFormatters = DateFormatters(Locale.US, clock, TimeZone.UTC) + assertThat(dateFormatters.formatDateWithFullFormat(Instant.parse(dat).toLocalDateTime(TimeZone.UTC))).isEqualTo("Friday, April 6, 1979") + } + /** * Create DefaultLastMessageFormatter and set current time to the provided date. */