Migrate to some newer date/time APIs

This commit is contained in:
arkon 2023-12-08 23:11:53 -05:00
parent 8779b263ab
commit ab9a26f6bd
18 changed files with 65 additions and 68 deletions

View file

@ -22,8 +22,8 @@ import tachiyomi.domain.chapter.service.ChapterRecognition
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
import java.lang.Long.max import java.lang.Long.max
import java.time.Instant
import java.time.ZonedDateTime import java.time.ZonedDateTime
import java.util.Date
import java.util.TreeSet import java.util.TreeSet
class SyncChaptersWithSource( class SyncChaptersWithSource(
@ -83,7 +83,7 @@ class SyncChaptersWithSource(
} }
} }
val rightNow = Date().time val rightNow = Instant.now().toEpochMilli()
// Used to not set upload date of older chapters // Used to not set upload date of older chapters
// to a higher value than newer chapters // to a higher value than newer chapters

View file

@ -10,8 +10,8 @@ import tachiyomi.domain.manga.repository.MangaRepository
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.time.Instant
import java.time.ZonedDateTime import java.time.ZonedDateTime
import java.util.Date
class UpdateManga( class UpdateManga(
private val mangaRepository: MangaRepository, private val mangaRepository: MangaRepository,
@ -46,14 +46,14 @@ class UpdateManga(
// Never refresh covers if the url is empty to avoid "losing" existing covers // Never refresh covers if the url is empty to avoid "losing" existing covers
remoteManga.thumbnail_url.isNullOrEmpty() -> null remoteManga.thumbnail_url.isNullOrEmpty() -> null
!manualFetch && localManga.thumbnailUrl == remoteManga.thumbnail_url -> null !manualFetch && localManga.thumbnailUrl == remoteManga.thumbnail_url -> null
localManga.isLocal() -> Date().time localManga.isLocal() -> Instant.now().toEpochMilli()
localManga.hasCustomCover(coverCache) -> { localManga.hasCustomCover(coverCache) -> {
coverCache.deleteFromCache(localManga, false) coverCache.deleteFromCache(localManga, false)
null null
} }
else -> { else -> {
coverCache.deleteFromCache(localManga, false) coverCache.deleteFromCache(localManga, false)
Date().time Instant.now().toEpochMilli()
} }
} }
@ -87,16 +87,16 @@ class UpdateManga(
} }
suspend fun awaitUpdateLastUpdate(mangaId: Long): Boolean { suspend fun awaitUpdateLastUpdate(mangaId: Long): Boolean {
return mangaRepository.update(MangaUpdate(id = mangaId, lastUpdate = Date().time)) return mangaRepository.update(MangaUpdate(id = mangaId, lastUpdate = Instant.now().toEpochMilli()))
} }
suspend fun awaitUpdateCoverLastModified(mangaId: Long): Boolean { suspend fun awaitUpdateCoverLastModified(mangaId: Long): Boolean {
return mangaRepository.update(MangaUpdate(id = mangaId, coverLastModified = Date().time)) return mangaRepository.update(MangaUpdate(id = mangaId, coverLastModified = Instant.now().toEpochMilli()))
} }
suspend fun awaitUpdateFavorite(mangaId: Long, favorite: Boolean): Boolean { suspend fun awaitUpdateFavorite(mangaId: Long, favorite: Boolean): Boolean {
val dateAdded = when (favorite) { val dateAdded = when (favorite) {
true -> Date().time true -> Instant.now().toEpochMilli()
false -> 0 false -> 0
} }
return mangaRepository.update( return mangaRepository.update(

View file

@ -33,7 +33,7 @@ import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.collectAsState import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.Date import java.time.Instant
object SettingsAppearanceScreen : SearchableSettings { object SettingsAppearanceScreen : SearchableSettings {
@ -123,7 +123,7 @@ object SettingsAppearanceScreen : SearchableSettings {
var currentLanguage by remember { var currentLanguage by remember {
mutableStateOf(AppCompatDelegate.getApplicationLocales().get(0)?.toLanguageTag() ?: "") mutableStateOf(AppCompatDelegate.getApplicationLocales().get(0)?.toLanguageTag() ?: "")
} }
val now = remember { Date().time } val now = remember { Instant.now().toEpochMilli() }
val dateFormat by uiPreferences.dateFormat().collectAsState() val dateFormat by uiPreferences.dateFormat().collectAsState()
val formattedNow = remember(dateFormat) { val formattedNow = remember(dateFormat) {

View file

@ -7,7 +7,7 @@ import androidx.compose.runtime.ReadOnlyComposable
import tachiyomi.core.i18n.stringResource import tachiyomi.core.i18n.stringResource
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource
import java.util.Date import java.time.Instant
import kotlin.time.Duration import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.minutes
@ -29,7 +29,7 @@ fun Duration.toDurationString(context: Context, fallback: String): String {
@Composable @Composable
@ReadOnlyComposable @ReadOnlyComposable
fun relativeTimeSpanString(epochMillis: Long): String { fun relativeTimeSpanString(epochMillis: Long): String {
val now = Date().time val now = Instant.now().toEpochMilli()
return when { return when {
epochMillis <= 0L -> stringResource(MR.strings.relative_time_span_never) epochMillis <= 0L -> stringResource(MR.strings.relative_time_span_never)
now - epochMillis < 1.minutes.inWholeMilliseconds -> stringResource( now - epochMillis < 1.minutes.inWholeMilliseconds -> stringResource(

View file

@ -25,7 +25,7 @@ import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.storage.service.StorageManager import tachiyomi.domain.storage.service.StorageManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.Date import java.time.Instant
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.minutes
import kotlin.time.toJavaDuration import kotlin.time.toJavaDuration
@ -52,7 +52,7 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete
return try { return try {
val location = BackupCreator(context).createBackup(uri, flags, isAutoBackup) val location = BackupCreator(context).createBackup(uri, flags, isAutoBackup)
if (isAutoBackup) { if (isAutoBackup) {
backupPreferences.lastAutoBackupTimestamp().set(Date().time) backupPreferences.lastAutoBackupTimestamp().set(Instant.now().toEpochMilli())
} else { } else {
notifier.showBackupComplete(UniFile.fromUri(context, location.toUri())!!) notifier.showBackupComplete(UniFile.fromUri(context, location.toUri())!!)
} }

View file

@ -69,8 +69,8 @@ import tachiyomi.i18n.MR
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File import java.io.File
import java.time.Instant
import java.time.ZonedDateTime import java.time.ZonedDateTime
import java.util.Date
import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
@ -111,7 +111,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
setForegroundSafely() setForegroundSafely()
libraryPreferences.lastUpdatedTimestamp().set(Date().time) libraryPreferences.lastUpdatedTimestamp().set(Instant.now().toEpochMilli())
val categoryId = inputData.getLong(KEY_CATEGORY, -1L) val categoryId = inputData.getLong(KEY_CATEGORY, -1L)
addMangaToQueue(categoryId) addMangaToQueue(categoryId)

View file

@ -23,7 +23,7 @@ import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
import java.io.InputStream import java.io.InputStream
import java.util.Date import java.time.Instant
class ImageSaver( class ImageSaver(
val context: Context, val context: Context,
@ -79,7 +79,7 @@ class ImageSaver(
MediaStore.Images.Media.RELATIVE_PATH to relativePath, MediaStore.Images.Media.RELATIVE_PATH to relativePath,
MediaStore.Images.Media.DISPLAY_NAME to image.name, MediaStore.Images.Media.DISPLAY_NAME to image.name,
MediaStore.Images.Media.MIME_TYPE to type.mime, MediaStore.Images.Media.MIME_TYPE to type.mime,
MediaStore.Images.Media.DATE_MODIFIED to Date().time * 1000, MediaStore.Images.Media.DATE_MODIFIED to Instant.now().toEpochMilli(),
) )
val picture = findUriOrDefault(relativePath, filename) { val picture = findUriOrDefault(relativePath, filename) {

View file

@ -26,7 +26,10 @@ import okhttp3.OkHttpClient
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withIOContext
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.Calendar import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId
import java.time.ZonedDateTime
import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.minutes
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
@ -328,13 +331,15 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
private fun parseDate(struct: JsonObject, dateKey: String): Long { private fun parseDate(struct: JsonObject, dateKey: String): Long {
return try { return try {
val date = Calendar.getInstance() return LocalDate
date.set( .of(
struct[dateKey]!!.jsonObject["year"]!!.jsonPrimitive.int, struct[dateKey]!!.jsonObject["year"]!!.jsonPrimitive.int,
struct[dateKey]!!.jsonObject["month"]!!.jsonPrimitive.int - 1, struct[dateKey]!!.jsonObject["month"]!!.jsonPrimitive.int,
struct[dateKey]!!.jsonObject["day"]!!.jsonPrimitive.int, struct[dateKey]!!.jsonObject["day"]!!.jsonPrimitive.int,
) )
date.timeInMillis .atStartOfDay(ZoneId.systemDefault())
.toInstant()
.toEpochMilli()
} catch (_: Exception) { } catch (_: Exception) {
0L 0L
} }
@ -349,12 +354,11 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
} }
} }
val calendar = Calendar.getInstance() val dateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(dateValue), ZoneId.systemDefault())
calendar.timeInMillis = dateValue
return buildJsonObject { return buildJsonObject {
put("year", calendar.get(Calendar.YEAR)) put("year", dateTime.year)
put("month", calendar.get(Calendar.MONTH) + 1) put("month", dateTime.monthValue)
put("day", calendar.get(Calendar.DAY_OF_MONTH)) put("day", dateTime.dayOfMonth)
} }
} }

View file

@ -17,7 +17,7 @@ import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.Date import java.time.Instant
import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.days
internal class ExtensionGithubApi { internal class ExtensionGithubApi {
@ -76,14 +76,16 @@ internal class ExtensionGithubApi {
fromAvailableExtensionList: Boolean = false, fromAvailableExtensionList: Boolean = false,
): List<Extension.Installed>? { ): List<Extension.Installed>? {
// Limit checks to once a day at most // Limit checks to once a day at most
if (!fromAvailableExtensionList && Date().time < lastExtCheck.get() + 1.days.inWholeMilliseconds) { if (!fromAvailableExtensionList &&
Instant.now().toEpochMilli() < lastExtCheck.get() + 1.days.inWholeMilliseconds
) {
return null return null
} }
val extensions = if (fromAvailableExtensionList) { val extensions = if (fromAvailableExtensionList) {
extensionManager.availableExtensionsFlow.value extensionManager.availableExtensionsFlow.value
} else { } else {
findExtensions().also { lastExtCheck.set(Date().time) } findExtensions().also { lastExtCheck.set(Instant.now().toEpochMilli()) }
} }
val installedExtensions = ExtensionLoader.loadExtensions(context) val installedExtensions = ExtensionLoader.loadExtensions(context)

View file

@ -53,7 +53,7 @@ import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.LoadingScreen import tachiyomi.presentation.core.screens.LoadingScreen
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.Date import java.time.Instant
@Composable @Composable
internal fun MigrateDialog( internal fun MigrateDialog(
@ -298,7 +298,7 @@ internal class MigrateDialogScreenModel(
favorite = true, favorite = true,
chapterFlags = oldManga.chapterFlags, chapterFlags = oldManga.chapterFlags,
viewerFlags = oldManga.viewerFlags, viewerFlags = oldManga.viewerFlags,
dateAdded = if (replace) oldManga.dateAdded else Date().time, dateAdded = if (replace) oldManga.dateAdded else Instant.now().toEpochMilli(),
), ),
) )
} }

View file

@ -50,7 +50,7 @@ import tachiyomi.domain.source.interactor.GetRemoteManga
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.Date import java.time.Instant
import eu.kanade.tachiyomi.source.model.Filter as SourceModelFilter import eu.kanade.tachiyomi.source.model.Filter as SourceModelFilter
class BrowseSourceScreenModel( class BrowseSourceScreenModel(
@ -225,7 +225,7 @@ class BrowseSourceScreenModel(
favorite = !manga.favorite, favorite = !manga.favorite,
dateAdded = when (manga.favorite) { dateAdded = when (manga.favorite) {
true -> 0 true -> 0
false -> Date().time false -> Instant.now().toEpochMilli()
}, },
) )

View file

@ -74,6 +74,7 @@ import tachiyomi.domain.source.service.SourceManager
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.time.Instant
import java.util.Date import java.util.Date
/** /**
@ -539,7 +540,7 @@ class ReaderViewModel @JvmOverloads constructor(
} }
fun restartReadTimer() { fun restartReadTimer() {
chapterReadStartTime = Date().time chapterReadStartTime = Instant.now().toEpochMilli()
} }
fun flushReadTimer() { fun flushReadTimer() {

View file

@ -49,7 +49,7 @@ import tachiyomi.domain.updates.interactor.GetUpdates
import tachiyomi.domain.updates.model.UpdatesWithRelations import tachiyomi.domain.updates.model.UpdatesWithRelations
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.Calendar import java.time.ZonedDateTime
import java.util.Date import java.util.Date
class UpdatesScreenModel( class UpdatesScreenModel(
@ -79,13 +79,10 @@ class UpdatesScreenModel(
init { init {
screenModelScope.launchIO { screenModelScope.launchIO {
// Set date limit for recent chapters // Set date limit for recent chapters
val calendar = Calendar.getInstance().apply { val limit = ZonedDateTime.now().minusMonths(3).toInstant()
time = Date()
add(Calendar.MONTH, -3)
}
combine( combine(
getUpdates.subscribe(calendar).distinctUntilChanged(), getUpdates.subscribe(limit).distinctUntilChanged(),
downloadCache.changes, downloadCache.changes,
downloadManager.queueState, downloadManager.queueState,
) { updates, _, _ -> updates } ) { updates, _, _ -> updates }

View file

@ -12,7 +12,7 @@ import tachiyomi.source.local.isLocal
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.InputStream import java.io.InputStream
import java.util.Date import java.time.Instant
/** /**
* Call before updating [Manga.thumbnail_url] to ensure old cover can be cleared from cache * Call before updating [Manga.thumbnail_url] to ensure old cover can be cleared from cache
@ -28,7 +28,7 @@ fun Manga.prepUpdateCover(coverCache: CoverCache, remoteManga: SManga, refreshSa
return when { return when {
isLocal() -> { isLocal() -> {
this.copy(coverLastModified = Date().time) this.copy(coverLastModified = Instant.now().toEpochMilli())
} }
hasCustomCover(coverCache) -> { hasCustomCover(coverCache) -> {
coverCache.deleteFromCache(this, false) coverCache.deleteFromCache(this, false)
@ -36,7 +36,7 @@ fun Manga.prepUpdateCover(coverCache: CoverCache, remoteManga: SManga, refreshSa
} }
else -> { else -> {
coverCache.deleteFromCache(this, false) coverCache.deleteFromCache(this, false)
this.copy(coverLastModified = Date().time) this.copy(coverLastModified = Instant.now().toEpochMilli())
} }
} }
} }
@ -44,7 +44,7 @@ fun Manga.prepUpdateCover(coverCache: CoverCache, remoteManga: SManga, refreshSa
fun Manga.removeCovers(coverCache: CoverCache = Injekt.get()): Manga { fun Manga.removeCovers(coverCache: CoverCache = Injekt.get()): Manga {
if (isLocal()) return this if (isLocal()) return this
return if (coverCache.deleteFromCache(this, true) > 0) { return if (coverCache.deleteFromCache(this, true) > 0) {
return copy(coverLastModified = Date().time) return copy(coverLastModified = Instant.now().toEpochMilli())
} else { } else {
this this
} }

View file

@ -8,6 +8,7 @@ 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.time.temporal.ChronoUnit
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
@ -38,13 +39,8 @@ fun Long.convertEpochMillisZone(
* @return date as time key * @return date as time key
*/ */
fun Long.toDateKey(): Date { fun Long.toDateKey(): Date {
val cal = Calendar.getInstance() val instant = Instant.ofEpochMilli(this)
cal.time = Date(this) return Date.from(instant.truncatedTo(ChronoUnit.DAYS))
cal[Calendar.HOUR_OF_DAY] = 0
cal[Calendar.MINUTE] = 0
cal[Calendar.SECOND] = 0
cal[Calendar.MILLISECOND] = 0
return cal.time
} }
private const val MILLISECONDS_IN_DAY = 86_400_000L private const val MILLISECONDS_IN_DAY = 86_400_000L

View file

@ -3,7 +3,7 @@ package tachiyomi.domain.updates.interactor
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import tachiyomi.domain.updates.model.UpdatesWithRelations import tachiyomi.domain.updates.model.UpdatesWithRelations
import tachiyomi.domain.updates.repository.UpdatesRepository import tachiyomi.domain.updates.repository.UpdatesRepository
import java.util.Calendar import java.time.Instant
class GetUpdates( class GetUpdates(
private val repository: UpdatesRepository, private val repository: UpdatesRepository,
@ -13,8 +13,8 @@ class GetUpdates(
return repository.awaitWithRead(read, after, limit = 500) return repository.awaitWithRead(read, after, limit = 500)
} }
fun subscribe(calendar: Calendar): Flow<List<UpdatesWithRelations>> { fun subscribe(instant: Instant): Flow<List<UpdatesWithRelations>> {
return repository.subscribeAll(calendar.time.time, limit = 500) return repository.subscribeAll(instant.toEpochMilli(), limit = 500)
} }
fun subscribe(read: Boolean, after: Long): Flow<List<UpdatesWithRelations>> { fun subscribe(read: Boolean, after: Long): Flow<List<UpdatesWithRelations>> {

View file

@ -45,8 +45,8 @@ import tachiyomi.presentation.widget.util.appWidgetBackgroundRadius
import tachiyomi.presentation.widget.util.calculateRowAndColumnCount import tachiyomi.presentation.widget.util.calculateRowAndColumnCount
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.Calendar import java.time.Instant
import java.util.Date import java.time.ZonedDateTime
abstract class BaseUpdatesGridGlanceWidget( abstract class BaseUpdatesGridGlanceWidget(
private val context: Context = Injekt.get<Application>(), private val context: Context = Injekt.get<Application>(),
@ -89,7 +89,7 @@ abstract class BaseUpdatesGridGlanceWidget(
val flow = remember { val flow = remember {
getUpdates getUpdates
.subscribe(false, DateLimit.timeInMillis) .subscribe(false, DateLimit.toEpochMilli())
.map { rawData -> .map { rawData ->
rawData.prepareData(rowCount, columnCount) rawData.prepareData(rowCount, columnCount)
} }
@ -147,10 +147,7 @@ abstract class BaseUpdatesGridGlanceWidget(
} }
companion object { companion object {
val DateLimit: Calendar val DateLimit: Instant
get() = Calendar.getInstance().apply { get() = ZonedDateTime.now().minusMonths(3).toInstant()
time = Date()
add(Calendar.MONTH, -3)
}
} }
} }

View file

@ -19,7 +19,7 @@ class WidgetManager(
fun Context.init(scope: LifecycleCoroutineScope) { fun Context.init(scope: LifecycleCoroutineScope) {
combine( combine(
getUpdates.subscribe(read = false, after = BaseUpdatesGridGlanceWidget.DateLimit.timeInMillis), getUpdates.subscribe(read = false, after = BaseUpdatesGridGlanceWidget.DateLimit.toEpochMilli()),
securityPreferences.useAuthenticator().changes(), securityPreferences.useAuthenticator().changes(),
transform = { a, _ -> a }, transform = { a, _ -> a },
) )