Refactor use of Java.util.date to Java.time.*, to fix localized date issues. (#402)
* Add support for localdate based relative times * Update History Screen to use new localdate based relative times * Update Updates Screen to use new localdate based relative times * Cleaned up date util classes * Updated build time display * Code cleanup * Fixed crash in settings * Updated Preferences item * Worker Info works * Fixed Tracker date display * Code changes to pass detekt
This commit is contained in:
@@ -5,7 +5,7 @@ import cafe.adriel.voyager.core.model.StateScreenModel
|
||||
import cafe.adriel.voyager.core.model.screenModelScope
|
||||
import eu.kanade.core.util.insertSeparators
|
||||
import eu.kanade.presentation.history.HistoryUiModel
|
||||
import eu.kanade.tachiyomi.util.lang.toDateKey
|
||||
import eu.kanade.tachiyomi.util.lang.toLocalDate
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@@ -28,7 +28,7 @@ import tachiyomi.domain.history.interactor.RemoveHistory
|
||||
import tachiyomi.domain.history.model.HistoryWithRelations
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.Date
|
||||
import java.time.LocalDate
|
||||
|
||||
class HistoryScreenModel(
|
||||
private val getHistory: GetHistory = Injekt.get(),
|
||||
@@ -60,10 +60,12 @@ class HistoryScreenModel(
|
||||
private fun List<HistoryWithRelations>.toHistoryUiModels(): List<HistoryUiModel> {
|
||||
return map { HistoryUiModel.Item(it) }
|
||||
.insertSeparators { before, after ->
|
||||
val beforeDate = before?.item?.readAt?.time?.toDateKey() ?: Date(0)
|
||||
val afterDate = after?.item?.readAt?.time?.toDateKey() ?: Date(0)
|
||||
val beforeDate = before?.item?.readAt?.time?.toLocalDate() ?: LocalDate.MIN
|
||||
val afterDate = after?.item?.readAt?.time?.toLocalDate() ?: LocalDate.MIN
|
||||
when {
|
||||
beforeDate.time != afterDate.time && afterDate.time != 0L -> HistoryUiModel.Header(afterDate)
|
||||
beforeDate.isAfter(afterDate)
|
||||
or afterDate.equals(LocalDate.MIN)
|
||||
or beforeDate.equals(LocalDate.MIN) -> HistoryUiModel.Header(afterDate)
|
||||
// Return null to avoid adding a separator between two items.
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.util.lang.toDateKey
|
||||
import eu.kanade.tachiyomi.util.lang.toLocalDate
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.mutate
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
@@ -45,8 +45,8 @@ import tachiyomi.domain.updates.interactor.GetUpdates
|
||||
import tachiyomi.domain.updates.model.UpdatesWithRelations
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.time.LocalDate
|
||||
import java.time.ZonedDateTime
|
||||
import java.util.Date
|
||||
|
||||
class UpdatesScreenModel(
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
@@ -374,12 +374,12 @@ class UpdatesScreenModel(
|
||||
return items
|
||||
.map { UpdatesUiModel.Item(it) }
|
||||
.insertSeparators { before, after ->
|
||||
val beforeDate = before?.item?.update?.dateFetch?.toDateKey() ?: Date(0)
|
||||
val afterDate = after?.item?.update?.dateFetch?.toDateKey() ?: Date(0)
|
||||
val beforeDate = before?.item?.update?.dateFetch?.toLocalDate() ?: LocalDate.MIN
|
||||
val afterDate = after?.item?.update?.dateFetch?.toLocalDate() ?: LocalDate.MIN
|
||||
when {
|
||||
beforeDate.time != afterDate.time && afterDate.time != 0L -> {
|
||||
UpdatesUiModel.Header(afterDate)
|
||||
}
|
||||
beforeDate.isAfter(afterDate)
|
||||
or afterDate.equals(LocalDate.MIN)
|
||||
or beforeDate.equals(LocalDate.MIN) -> UpdatesUiModel.Header(afterDate)
|
||||
// Return null to avoid adding a separator between two items.
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -6,15 +6,17 @@ import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.i18n.MR
|
||||
import java.text.DateFormat
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
fun Date.toDateTimestampString(dateFormatter: DateFormat): String {
|
||||
val date = dateFormatter.format(this)
|
||||
val time = DateFormat.getTimeInstance(DateFormat.SHORT).format(this)
|
||||
fun LocalDateTime.toDateTimestampString(dateTimeFormatter: DateTimeFormatter): String {
|
||||
val date = dateTimeFormatter.format(this)
|
||||
val time = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(this)
|
||||
return "$date $time"
|
||||
}
|
||||
|
||||
@@ -32,52 +34,28 @@ fun Long.convertEpochMillisZone(
|
||||
.toEpochMilli()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get date as time key
|
||||
*
|
||||
* @param date desired date
|
||||
* @return date as time key
|
||||
*/
|
||||
fun Long.toDateKey(): Date {
|
||||
val instant = Instant.ofEpochMilli(this)
|
||||
return Date.from(instant.truncatedTo(ChronoUnit.DAYS))
|
||||
fun Long.toLocalDate(): LocalDate {
|
||||
return LocalDate.ofInstant(Instant.ofEpochMilli(this), ZoneId.systemDefault())
|
||||
}
|
||||
|
||||
fun Date.toRelativeString(
|
||||
fun LocalDate.toRelativeSting(
|
||||
context: Context,
|
||||
relative: Boolean = true,
|
||||
dateFormat: DateFormat = DateFormat.getDateInstance(DateFormat.SHORT),
|
||||
dateFormat: DateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT),
|
||||
): String {
|
||||
if (!relative) {
|
||||
return dateFormat.format(this)
|
||||
}
|
||||
val now = Date()
|
||||
val difference = now.timeWithOffset.floorNearest(MILLISECONDS_IN_DAY) -
|
||||
this.timeWithOffset.floorNearest(MILLISECONDS_IN_DAY)
|
||||
val days = difference.floorDiv(MILLISECONDS_IN_DAY).toInt()
|
||||
val now = LocalDate.now()
|
||||
val difference = ChronoUnit.DAYS.between(this, now)
|
||||
return when {
|
||||
difference < 0 -> dateFormat.format(this)
|
||||
difference < MILLISECONDS_IN_DAY -> context.stringResource(MR.strings.relative_time_today)
|
||||
difference < MILLISECONDS_IN_DAY.times(7) -> context.pluralStringResource(
|
||||
difference < 0 -> difference.toString()
|
||||
difference < 1 -> context.stringResource(MR.strings.relative_time_today)
|
||||
difference < 7 -> context.pluralStringResource(
|
||||
MR.plurals.relative_time,
|
||||
days,
|
||||
days,
|
||||
difference.toInt(),
|
||||
difference.toInt(),
|
||||
)
|
||||
else -> dateFormat.format(this)
|
||||
}
|
||||
}
|
||||
|
||||
private const val MILLISECONDS_IN_DAY = 86_400_000L
|
||||
|
||||
private val Date.timeWithOffset: Long
|
||||
get() {
|
||||
return Calendar.getInstance().run {
|
||||
time = this@timeWithOffset
|
||||
val dstOffset = get(Calendar.DST_OFFSET)
|
||||
this@timeWithOffset.time + timeZone.rawOffset + dstOffset
|
||||
}
|
||||
}
|
||||
|
||||
private fun Long.floorNearest(to: Long): Long {
|
||||
return this.floorDiv(to) * to
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user