diff --git a/CHANGELOG.md b/CHANGELOG.md index 128a7ddd3..6e49d64bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co ## [Unreleased] ### Fixed - Fixed app and extension update check running again on configuration change ([@AntsyLich](https://github.com/AntsyLich)) ([#3708](https://github.com/mihonapp/mihon/pull/3708)) +- Fixed MangaBaka user start/finish dates drifting in negative offset timezones ([@MajorTanya](https://github.com/MajorTanya)) ([#3711](https://github.com/mihonapp/mihon/pull/3711)) ## [v0.20.4] - 2026-08-05 ### Fixed diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangabaka/MangaBakaApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangabaka/MangaBakaApi.kt index 02ec3b5a6..503ea9aac 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangabaka/MangaBakaApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangabaka/MangaBakaApi.kt @@ -22,6 +22,9 @@ import eu.kanade.tachiyomi.network.awaitSuccess import eu.kanade.tachiyomi.network.parseAs import eu.kanade.tachiyomi.util.PkceUtil import eu.kanade.tachiyomi.util.lang.toLocalDate +import kotlinx.datetime.LocalDate +import kotlinx.datetime.TimeZone +import kotlinx.datetime.atStartOfDayIn import kotlinx.serialization.json.Json import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.json.put @@ -35,7 +38,6 @@ import java.math.RoundingMode import java.security.SecureRandom import java.util.Base64 import java.util.Locale -import kotlin.time.Instant import tachiyomi.domain.track.model.Track as DomainTrack class MangaBakaApi( @@ -123,9 +125,8 @@ class MangaBakaApi( title = additionalData.chooseBestTitle() status = userData.getStatus() score = userData.rating?.toDouble() ?: 0.0 - started_reading_date = userData.startDate?.let { Instant.parse(it).toEpochMilliseconds() } ?: 0 - finished_reading_date = - userData.finishDate?.let { Instant.parse(it).toEpochMilliseconds() } ?: 0 + started_reading_date = parseIsoDateAsLocalStartOfDay(userData.startDate) ?: 0 + finished_reading_date = parseIsoDateAsLocalStartOfDay(userData.finishDate) ?: 0 last_chapter_read = userData.progressChapter ?: 0.0 private = userData.isPrivate } @@ -266,6 +267,16 @@ class MangaBakaApi( fun verifyOAuthState(state: String): Boolean = state == oauthStateParam + private fun parseIsoDateAsLocalStartOfDay(isoDate: String?): Long? { + // The v1 API returns full ISO 8601 strings with a midnight-UTC-truncated time component, regardless of the + // actual time of the change made. + return isoDate + ?.substringBefore("T") + ?.let { LocalDate.parse(it) } + ?.atStartOfDayIn(TimeZone.currentSystemDefault()) + ?.toEpochMilliseconds() + } + companion object { private const val CLIENT_ID = "zEZYMHXLWsLsafgbvJHXqzGvqQNOdkpo"