From d35a420c29d34de289c4958316280033c7e336e1 Mon Sep 17 00:00:00 2001 From: dankito Date: Sun, 18 Apr 2021 22:49:39 +0200 Subject: [PATCH] Parsing date and time now manually as Java's DateFormat is not thread safe causing a lot of curious errors when executed in parallel --- .../utils/multiplatform/DateFormatter.kt | 4 +++- .../datenelemente/abgeleiteteformate/Datum.kt | 20 ++++++++++++++++- .../abgeleiteteformate/Uhrzeit.kt | 22 +++++++++++++++++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/common/src/commonMain/kotlin/net/dankito/utils/multiplatform/DateFormatter.kt b/common/src/commonMain/kotlin/net/dankito/utils/multiplatform/DateFormatter.kt index bf54f83d..d89beaa3 100644 --- a/common/src/commonMain/kotlin/net/dankito/utils/multiplatform/DateFormatter.kt +++ b/common/src/commonMain/kotlin/net/dankito/utils/multiplatform/DateFormatter.kt @@ -1,6 +1,8 @@ package net.dankito.utils.multiplatform - +/** + * Be aware that Java DateFormat is not thread safe! + */ expect class DateFormatter constructor(pattern: String) { constructor(dateStyle: DateFormatStyle) diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/abgeleiteteformate/Datum.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/abgeleiteteformate/Datum.kt index d16a7d3a..d3abecc7 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/abgeleiteteformate/Datum.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/abgeleiteteformate/Datum.kt @@ -4,6 +4,7 @@ import net.dankito.banking.fints.messages.Existenzstatus import net.dankito.banking.fints.messages.datenelemente.basisformate.NumerischesDatenelement import net.dankito.utils.multiplatform.Date import net.dankito.utils.multiplatform.DateFormatter +import net.dankito.utils.multiplatform.log.LoggerFactory /** @@ -19,12 +20,29 @@ open class Datum(date: Int?, existenzstatus: Existenzstatus) : NumerischesDatene val HbciDateFormat = DateFormatter(HbciDateFormatString) + private val log = LoggerFactory.getLogger(Datum::class) + + fun format(date: Date): String { return HbciDateFormat.format(date) // TODO: is this correct? } fun parse(dateString: String): Date { - return HbciDateFormat.parse(dateString) !! + // do not use DateFormatter as Java DateFormat is not thread safe, resulting in a lot of curious errors in parallel execution + + if (dateString.length == 8) { + try { + val year = dateString.substring(0, 4) + val month = dateString.substring(4, 6) + val day = dateString.substring(6, 8) + + return Date(year.toInt(), month.toInt(), day.toInt()) + } catch (e: Exception) { + log.error(e) { "Could not parse date string '$dateString' to HBCI date" } + } + } + + throw IllegalArgumentException("Cannot parse '$dateString' to HBCI Date. Only dates in format '$HbciDateFormatString' are allowed in HBCI / FinTS.") } } diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/abgeleiteteformate/Uhrzeit.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/abgeleiteteformate/Uhrzeit.kt index a0f0ca88..afe8b0fe 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/abgeleiteteformate/Uhrzeit.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/datenelemente/abgeleiteteformate/Uhrzeit.kt @@ -4,6 +4,7 @@ import net.dankito.banking.fints.messages.Existenzstatus import net.dankito.banking.fints.messages.datenelemente.basisformate.ZiffernDatenelement import net.dankito.utils.multiplatform.Date import net.dankito.utils.multiplatform.DateFormatter +import net.dankito.utils.multiplatform.log.LoggerFactory /** @@ -20,12 +21,29 @@ open class Uhrzeit(time: Int?, existenzstatus: Existenzstatus) : ZiffernDatenele val HbciTimeFormat = DateFormatter(HbciTimeFormatString) + private val log = LoggerFactory.getLogger(Uhrzeit::class) + + fun format(time: Date): String { return HbciTimeFormat.format(time) // TODO: is this correct? } - fun parse(dateString: String): Date { - return HbciTimeFormat.parse(dateString) !! + fun parse(timeString: String): Date { + // do not use DateFormatter as Java DateFormat is not thread safe, resulting in a lot of curious errors in parallel execution + + if (timeString.length == 6) { + try { + val hour = timeString.substring(0, 2) + val minute = timeString.substring(2, 4) + val second = timeString.substring(4, 6) + + return Date(0, 0, 0, hour.toInt(), minute.toInt(), second.toInt()) + } catch (e: Exception) { + log.error(e) { "Could not parse time string '$timeString' to HBCI time" } + } + } + + throw IllegalArgumentException("Cannot parse '$timeString' to HBCI Time. Only times in format '${Uhrzeit.HbciTimeFormatString}' are allowed in HBCI / FinTS.") } }