Create module dateformatter

This commit is contained in:
Benoit Marty 2023-02-06 18:09:18 +01:00 committed by Benoit Marty
parent c3a7ab1de4
commit ae4237abb5
12 changed files with 119 additions and 10 deletions

View file

@ -41,7 +41,7 @@ dependencies {
implementation(projects.libraries.designsystem)
implementation(projects.libraries.elementresources)
implementation(projects.libraries.uiStrings)
implementation(libs.datetime)
implementation(projects.libraries.dateformatter)
implementation(libs.accompanist.placeholder)
testImplementation(libs.test.junit)

View file

@ -1,102 +0,0 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.roomlist
import android.text.format.DateFormat
import android.text.format.DateUtils
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toJavaLocalDate
import kotlinx.datetime.toJavaLocalDateTime
import kotlinx.datetime.toLocalDateTime
import java.time.Period
import java.time.format.DateTimeFormatter
import java.util.Locale
import javax.inject.Inject
import kotlin.math.absoluteValue
class LastMessageFormatter @Inject constructor() {
private val clock: Clock = Clock.System
private val locale: Locale = Locale.getDefault()
private val onlyTimeFormatter: DateTimeFormatter by lazy {
val pattern = DateFormat.getBestDateTimePattern(locale, "HH:mm")
DateTimeFormatter.ofPattern(pattern)
}
private val dateWithMonthFormatter: DateTimeFormatter by lazy {
val pattern = DateFormat.getBestDateTimePattern(locale, "d MMM")
DateTimeFormatter.ofPattern(pattern)
}
private val dateWithYearFormatter: DateTimeFormatter by lazy {
val pattern = DateFormat.getBestDateTimePattern(locale, "dd.MM.yyyy")
DateTimeFormatter.ofPattern(pattern)
}
fun format(timestamp: Long?): String {
if (timestamp == null) return ""
val now: Instant = clock.now()
val tsInstant = Instant.fromEpochMilliseconds(timestamp)
val nowDateTime = now.toLocalDateTime(TimeZone.currentSystemDefault())
val tsDateTime = tsInstant.toLocalDateTime(TimeZone.currentSystemDefault())
val isSameDay = nowDateTime.date == tsDateTime.date
return when {
isSameDay -> {
onlyTimeFormatter.format(tsDateTime.toJavaLocalDateTime())
}
else -> {
formatDate(tsDateTime, nowDateTime)
}
}
}
private fun formatDate(
date: LocalDateTime,
currentDate: LocalDateTime,
): String {
val period = Period.between(date.date.toJavaLocalDate(), currentDate.date.toJavaLocalDate())
return if (period.years.absoluteValue >= 1) {
formatDateWithYear(date)
} else if (period.days.absoluteValue < 2 && period.months.absoluteValue < 1) {
getRelativeDay(date.toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds())
} else {
formatDateWithMonth(date)
}
}
private fun formatDateWithMonth(localDateTime: LocalDateTime): String {
return dateWithMonthFormatter.format(localDateTime.toJavaLocalDateTime())
}
private fun formatDateWithYear(localDateTime: LocalDateTime): String {
return dateWithYearFormatter.format(localDateTime.toJavaLocalDateTime())
}
private fun getRelativeDay(ts: Long): String {
return DateUtils.getRelativeTimeSpanString(
ts,
clock.now().toEpochMilliseconds(),
DateUtils.DAY_IN_MILLIS,
DateUtils.FORMAT_SHOW_WEEKDAY
).toString()
}
}

View file

@ -31,6 +31,7 @@ import io.element.android.features.roomlist.model.RoomListRoomSummaryPlaceholder
import io.element.android.features.roomlist.model.RoomListState
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.coroutine.parallelMap
import io.element.android.libraries.dateformatter.LastMessageFormatter
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.MatrixClient

View file

@ -24,6 +24,7 @@ import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomlist.model.RoomListEvents
import io.element.android.features.roomlist.model.RoomListRoomSummary
import io.element.android.libraries.dateformatter.impl.DefaultLastMessageFormatter
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.matrix.core.SessionId
import io.element.android.libraries.matrixtest.FakeMatrixClient
@ -45,7 +46,7 @@ class RoomListPresenterTests {
FakeMatrixClient(
SessionId("sessionId")
),
LastMessageFormatter()
DefaultLastMessageFormatter()
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
@ -63,7 +64,7 @@ class RoomListPresenterTests {
FakeMatrixClient(
SessionId("sessionId")
),
LastMessageFormatter()
DefaultLastMessageFormatter()
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
@ -85,7 +86,7 @@ class RoomListPresenterTests {
sessionId = SessionId("sessionId"),
roomSummaryDataSource = roomSummaryDataSource
),
LastMessageFormatter()
DefaultLastMessageFormatter()
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
@ -111,7 +112,7 @@ class RoomListPresenterTests {
sessionId = SessionId("sessionId"),
roomSummaryDataSource = roomSummaryDataSource
),
LastMessageFormatter()
DefaultLastMessageFormatter()
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()
@ -142,7 +143,7 @@ class RoomListPresenterTests {
sessionId = SessionId("sessionId"),
roomSummaryDataSource = roomSummaryDataSource
),
LastMessageFormatter()
DefaultLastMessageFormatter()
)
moleculeFlow(RecompositionClock.Immediate) {
presenter.present()