From db0c2d764682eb1aabaf4f7d23f6d4311ddb85ac Mon Sep 17 00:00:00 2001 From: kasperskier <95685115+kasperskier@users.noreply.github.com> Date: Wed, 1 Jun 2022 10:42:46 +0800 Subject: [PATCH] Make date formatters thread-safe (#12014) --- .../multisrc/comicgamma/ComicGamma.kt | 34 ++++++++++++++----- .../comicgamma/ComicGammaGenerator.kt | 2 +- src/ja/mangacross/build.gradle | 2 +- .../extension/ja/mangacross/MangaCrossDto.kt | 32 +++++++++-------- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/comicgamma/ComicGamma.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/comicgamma/ComicGamma.kt index abaa0dcae..4ef60071b 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/comicgamma/ComicGamma.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/comicgamma/ComicGamma.kt @@ -10,7 +10,7 @@ import eu.kanade.tachiyomi.source.online.ParsedHttpSource import org.jsoup.nodes.Document import org.jsoup.nodes.Element import rx.Observable -import java.text.DateFormat.getDateInstance +import java.text.DateFormat.getDateTimeInstance import java.text.SimpleDateFormat import java.util.Locale import java.util.TimeZone @@ -63,7 +63,7 @@ open class ComicGamma( val dateStr = nextDate.textNodes() .filter { it.text().contains("【次回更新】") }[0] .text().trim().removePrefix("【次回更新】") - val localDate = JST_FORMAT.parse(dateStr)?.let { LOCAL_FORMAT.format(it) } + val localDate = JST_FORMAT_DESC.parseJST(dateStr)?.let { LOCAL_FORMAT_DESC.format(it) } if (localDate != null) description = "【Next/Repeat: $localDate】\n$description" } } @@ -79,9 +79,17 @@ open class ComicGamma( it.text().contains("集中連載") || it.text().contains("配信中!!") }.joinToString("/") { it.text() } name = "$chapterNumber $title" - val date = element.select(".episode_caption").textNodes().firstOrNull { it.text().contains("【公開日】") } - ?.text()?.trim()?.removePrefix("【公開日】") - date_upload = date?.let { JST_FORMAT.parse(it)?.time } ?: -1L // hide unknown ones + element.select(".episode_caption").textNodes().forEach { + if (it.text().contains("【公開日】")) { + val date = it.text().trim().removePrefix("【公開日】") + date_upload = JST_FORMAT_LIST.parseJST(date)!!.time + } else if (it.text().contains("【次回更新】")) { + val date = it.text().trim().removePrefix("【次回更新】") + val localDate = JST_FORMAT_LIST.parseJST(date)?.let { LOCAL_FORMAT_LIST.format(it) } + if (localDate != null) scanlator = "~$localDate" + } + } + if (date_upload <= 0L) date_upload = -1L // hide unknown ones } override fun pageListParse(document: Document) = @@ -91,10 +99,20 @@ open class ComicGamma( override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.") + // for thread-safety (of subclasses) + private val JST_FORMAT_DESC = getJSTFormat() + private val JST_FORMAT_LIST = getJSTFormat() + private val LOCAL_FORMAT_DESC = getDateTimeInstance() + private val LOCAL_FORMAT_LIST = getDateTimeInstance() + companion object { - private val JST_FORMAT by lazy { - SimpleDateFormat("yyyy年M月dd日(E)", Locale.JAPANESE).apply { timeZone = TimeZone.getTimeZone("JST") } + private fun SimpleDateFormat.parseJST(date: String) = parse(date)?.apply { + time += 12 * 3600 * 1000 // updates at 12 noon } - private val LOCAL_FORMAT by lazy { getDateInstance() } + + private fun getJSTFormat() = + SimpleDateFormat("yyyy年M月dd日(E)", Locale.JAPANESE).apply { + timeZone = TimeZone.getTimeZone("GMT+09:00") + } } } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/comicgamma/ComicGammaGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/comicgamma/ComicGammaGenerator.kt index c37fc1d1a..9a2599729 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/comicgamma/ComicGammaGenerator.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/comicgamma/ComicGammaGenerator.kt @@ -6,7 +6,7 @@ import generator.ThemeSourceGenerator class ComicGammaGenerator : ThemeSourceGenerator { override val themeClass = "ComicGamma" override val themePkg = "comicgamma" - override val baseVersionCode = 1 + override val baseVersionCode = 2 override val sources = listOf( SingleLang( name = "Web Comic Gamma", diff --git a/src/ja/mangacross/build.gradle b/src/ja/mangacross/build.gradle index 830e3230c..ec2093408 100644 --- a/src/ja/mangacross/build.gradle +++ b/src/ja/mangacross/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'Manga Cross' pkgNameSuffix = 'ja.mangacross' extClass = '.MangaCross' - extVersionCode = 3 + extVersionCode = 4 } apply from: "$rootDir/common.gradle" diff --git a/src/ja/mangacross/src/eu/kanade/tachiyomi/extension/ja/mangacross/MangaCrossDto.kt b/src/ja/mangacross/src/eu/kanade/tachiyomi/extension/ja/mangacross/MangaCrossDto.kt index ae8297167..5b5d27ed2 100644 --- a/src/ja/mangacross/src/eu/kanade/tachiyomi/extension/ja/mangacross/MangaCrossDto.kt +++ b/src/ja/mangacross/src/eu/kanade/tachiyomi/extension/ja/mangacross/MangaCrossDto.kt @@ -88,16 +88,6 @@ data class MCEpisodeList( val total_pages: Int, ) -private val jstDate by lazy { - SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ENGLISH).apply { - timeZone = TimeZone.getTimeZone("GMT+09:00") - } -} - -private val localDate by lazy { getDateTimeInstance() } - -private fun parseJSTDate(date: String) = date.removeSuffix("+09:00").let { jstDate.parse(it) }!! - @Serializable data class MCEpisode( // val id: Long, @@ -121,21 +111,35 @@ data class MCEpisode( val prefix = if (status == "public") "" else "🔒 " name = "$prefix$volume $title" // milliseconds are always 000 - date_upload = parseJSTDate(publish_start).time + date_upload = JST_FORMAT_LIST.parseJST(publish_start)!!.time // show end date in scanlator field - scanlator = publish_end?.let { "~" + localDate.format(parseJSTDate(it)) } + scanlator = publish_end?.let { "~" + LOCAL_FORMAT_LIST.format(JST_FORMAT_LIST.parseJST(it)!!) } } fun getNextDatePrefix(): String? = when { !episode_next_date.isNullOrEmpty() -> { - val date = parseJSTDate(episode_next_date).apply { + val date = JST_FORMAT_DESC.parseJST(episode_next_date)!!.apply { time += 10 * 3600 * 1000 // 10 am JST } - "【Next: ${localDate.format(date)}】" + "【Next: ${LOCAL_FORMAT_DESC.format(date)}】" } !next_date_customize_text.isNullOrEmpty() -> "【$next_date_customize_text】" else -> null } + + companion object { + // for thread-safety + private val JST_FORMAT_DESC = getJSTFormat() + private val JST_FORMAT_LIST = getJSTFormat() + private val LOCAL_FORMAT_DESC = getDateTimeInstance() + private val LOCAL_FORMAT_LIST = getDateTimeInstance() + + private fun SimpleDateFormat.parseJST(date: String) = parse(date.removeSuffix("+09:00")) + private fun getJSTFormat() = + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ENGLISH).apply { + timeZone = TimeZone.getTimeZone("GMT+09:00") + } + } } @Serializable