Consistently use absolute date strings everywhere

Closes #9781
This commit is contained in:
arkon 2023-09-20 22:49:15 -04:00
parent 9e04f14a7b
commit b08d604d2a
5 changed files with 3 additions and 115 deletions

View file

@ -3,8 +3,6 @@ package eu.kanade.presentation.components
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import eu.kanade.tachiyomi.util.lang.toRelativeString
import tachiyomi.presentation.core.components.ListGroupHeader import tachiyomi.presentation.core.components.ListGroupHeader
import java.text.DateFormat import java.text.DateFormat
import java.util.Date import java.util.Date
@ -15,11 +13,10 @@ fun RelativeDateHeader(
date: Date, date: Date,
dateFormat: DateFormat, dateFormat: DateFormat,
) { ) {
val context = LocalContext.current
ListGroupHeader( ListGroupHeader(
modifier = modifier, modifier = modifier,
text = remember { text = remember {
date.toRelativeString(context, dateFormat) dateFormat.format(date)
}, },
) )
} }

View file

@ -63,7 +63,6 @@ import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.getNameForMangaInfo import eu.kanade.tachiyomi.source.getNameForMangaInfo
import eu.kanade.tachiyomi.ui.manga.ChapterItem import eu.kanade.tachiyomi.ui.manga.ChapterItem
import eu.kanade.tachiyomi.ui.manga.MangaScreenModel import eu.kanade.tachiyomi.ui.manga.MangaScreenModel
import eu.kanade.tachiyomi.util.lang.toRelativeString
import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.copyToClipboard
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.service.missingChaptersCount import tachiyomi.domain.chapter.service.missingChaptersCount
@ -740,7 +739,7 @@ private fun LazyListScope.sharedChapterItems(
date = chapterItem.chapter.dateUpload date = chapterItem.chapter.dateUpload
.takeIf { it > 0L } .takeIf { it > 0L }
?.let { ?.let {
Date(it).toRelativeString(context, dateFormat) dateFormat.format(Date(it))
}, },
readProgress = chapterItem.chapter.lastPageRead readProgress = chapterItem.chapter.lastPageRead
.takeIf { !chapterItem.chapter.read && it > 0L } .takeIf { !chapterItem.chapter.read && it > 0L }

View file

@ -20,7 +20,6 @@ import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.util.lang.toDateKey import eu.kanade.tachiyomi.util.lang.toDateKey
import eu.kanade.tachiyomi.util.lang.toRelativeString
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
@ -384,7 +383,7 @@ class UpdatesScreenModel(
val afterDate = after?.item?.update?.dateFetch?.toDateKey() ?: Date(0) val afterDate = after?.item?.update?.dateFetch?.toDateKey() ?: Date(0)
when { when {
beforeDate.time != afterDate.time && afterDate.time != 0L -> { beforeDate.time != afterDate.time && afterDate.time != 0L -> {
val text = afterDate.toRelativeString(context, dateFormat) val text = dateFormat.format(afterDate)
UpdatesUiModel.Header(text) UpdatesUiModel.Header(text)
} }
// Return null to avoid adding a separator between two items. // Return null to avoid adding a separator between two items.

View file

@ -1,14 +1,11 @@
package eu.kanade.tachiyomi.util.lang package eu.kanade.tachiyomi.util.lang
import android.content.Context
import eu.kanade.tachiyomi.R
import java.text.DateFormat import java.text.DateFormat
import java.time.Instant import java.time.Instant
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.ZoneId import java.time.ZoneId
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.TimeZone
fun Date.toDateTimestampString(dateFormatter: DateFormat): String { fun Date.toDateTimestampString(dateFormatter: DateFormat): String {
val date = dateFormatter.format(this) val date = dateFormatter.format(this)
@ -45,101 +42,3 @@ fun Long.toDateKey(): Date {
cal[Calendar.MILLISECOND] = 0 cal[Calendar.MILLISECOND] = 0
return cal.time return cal.time
} }
/**
* Convert epoch long to Calendar instance
*
* @return Calendar instance at supplied epoch time. Null if epoch was 0.
*/
fun Long.toCalendar(): Calendar? {
if (this == 0L) {
return null
}
val cal = Calendar.getInstance()
cal.timeInMillis = this
return cal
}
/**
* Convert local time millisecond value to Calendar instance in UTC
*
* @return UTC Calendar instance at supplied time. Null if time is 0.
*/
fun Long.toUtcCalendar(): Calendar? {
if (this == 0L) {
return null
}
val rawCalendar = Calendar.getInstance().apply {
timeInMillis = this@toUtcCalendar
}
return Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply {
clear()
set(
rawCalendar.get(Calendar.YEAR),
rawCalendar.get(Calendar.MONTH),
rawCalendar.get(Calendar.DAY_OF_MONTH),
rawCalendar.get(Calendar.HOUR_OF_DAY),
rawCalendar.get(Calendar.MINUTE),
rawCalendar.get(Calendar.SECOND),
)
}
}
/**
* Convert UTC time millisecond to Calendar instance in local time zone
*
* @return local Calendar instance at supplied UTC time. Null if time is 0.
*/
fun Long.toLocalCalendar(): Calendar? {
if (this == 0L) {
return null
}
val rawCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply {
timeInMillis = this@toLocalCalendar
}
return Calendar.getInstance().apply {
clear()
set(
rawCalendar.get(Calendar.YEAR),
rawCalendar.get(Calendar.MONTH),
rawCalendar.get(Calendar.DAY_OF_MONTH),
rawCalendar.get(Calendar.HOUR_OF_DAY),
rawCalendar.get(Calendar.MINUTE),
rawCalendar.get(Calendar.SECOND),
)
}
}
private const val MILLISECONDS_IN_DAY = 86_400_000L
fun Date.toRelativeString(
context: Context,
dateFormat: DateFormat = DateFormat.getDateInstance(DateFormat.SHORT),
): String {
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()
return when {
difference < 0 -> dateFormat.format(this)
difference < MILLISECONDS_IN_DAY -> context.getString(R.string.relative_time_today)
difference < MILLISECONDS_IN_DAY.times(7) -> context.resources.getQuantityString(
R.plurals.relative_time,
days,
days,
)
else -> dateFormat.format(this)
}
}
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
}
}
fun Long.floorNearest(to: Long): Long {
return this.floorDiv(to) * to
}

View file

@ -223,12 +223,6 @@
<string name="pref_show_nsfw_source">Show in sources and extensions lists</string> <string name="pref_show_nsfw_source">Show in sources and extensions lists</string>
<string name="parental_controls_info">This does not prevent unofficial or potentially incorrectly flagged extensions from surfacing NSFW (18+) content within the app.</string> <string name="parental_controls_info">This does not prevent unofficial or potentially incorrectly flagged extensions from surfacing NSFW (18+) content within the app.</string>
<string name="relative_time_today">Today</string>
<plurals name="relative_time">
<item quantity="one">Yesterday</item>
<item quantity="other">%1$d days ago</item>
</plurals>
<!-- Library section --> <!-- Library section -->
<string name="pref_category_display">Display</string> <string name="pref_category_display">Display</string>
<string name="pref_library_columns">Grid size</string> <string name="pref_library_columns">Grid size</string>