libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 313f461250a03566dc850000229420c4355e0206
parent d530bd9c9526e130561bb346a280215b38a89f13
Author: MS <ms@taler.net>
Date:   Mon, 25 May 2020 18:01:30 +0200

migrating to java.time

Diffstat:
Mnexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt | 6++++--
Mnexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt | 6+++---
Mnexus/src/main/kotlin/tech/libeufin/nexus/Main.kt | 15+++++++++------
Msandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt | 21++++++++++++---------
Mutil/src/main/kotlin/time.kt | 35++++++++++++++++++++++-------------
5 files changed, 50 insertions(+), 33 deletions(-)

diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt @@ -113,6 +113,9 @@ fun processCamtMessage( if (acct == null) { throw NexusError(HttpStatusCode.NotFound, "user not found") } + val bookingDate = parseDashedDate( + camt53doc.pickString("//*[local-name()='BookgDt']//*[local-name()='Dt']") + ) RawBankTransactionEntity.new { bankAccount = acct unstructuredRemittanceInformation = @@ -121,8 +124,7 @@ fun processCamtMessage( currency = camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Amt']/@Ccy") amount = camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Amt']") status = camt53doc.pickString("//*[local-name()='Ntry']//*[local-name()='Sts']") - bookingDate = - parseDashedDate(camt53doc.pickString("//*[local-name()='BookgDt']//*[local-name()='Dt']")).millis + this.bookingDate = bookingDate.millis() counterpartIban = camt53doc.pickString("//*[local-name()='${if (this.transactionType == "DBIT") "CdtrAcct" else "DbtrAcct"}']//*[local-name()='IBAN']") counterpartName = diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/JSON.kt @@ -5,9 +5,9 @@ import com.fasterxml.jackson.annotation.JsonSubTypes import com.fasterxml.jackson.annotation.JsonTypeInfo import com.fasterxml.jackson.annotation.JsonTypeName import com.fasterxml.jackson.databind.JsonNode -import org.joda.time.DateTime import tech.libeufin.util.* import java.time.LocalDate +import java.time.LocalDateTime data class EbicsBackupRequestJson( val passphrase: String @@ -22,7 +22,7 @@ data class EbicsStandardOrderParamsJson(val dateRange: EbicsDateRangeJson?) { var dateRange: EbicsDateRange? = if (this.dateRange != null) { EbicsDateRange( LocalDate.parse(this.dateRange.start ?: "1970-01-31"), - LocalDate.parse(this.dateRange.end ?: DateTime.now().toDashedDate()) + LocalDate.parse(this.dateRange.end ?: LocalDateTime.now().toDashedDate()) ) } else { null @@ -165,7 +165,7 @@ data class PaymentStatus( val creditorName: String, val amount: String, val subject: String, - val submissionDate: String, + val submissionDate: String?, val preparationDate: String ) diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt @@ -58,7 +58,6 @@ import io.ktor.utils.io.jvm.javaio.toByteReadChannel import io.ktor.utils.io.jvm.javaio.toInputStream import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.transactions.transaction -import org.joda.time.DateTime import org.slf4j.Logger import org.slf4j.LoggerFactory import org.slf4j.event.Level @@ -69,6 +68,7 @@ import java.util.* import java.util.zip.InflaterInputStream import javax.crypto.EncryptedPrivateKeyInfo import javax.sql.rowset.serial.SerialBlob +import java.time.LocalDateTime data class NexusError(val statusCode: HttpStatusCode, val reason: String) : Exception("${reason} (HTTP status $statusCode)") @@ -442,6 +442,7 @@ fun serverMain() { val preparedPayment = preparedPayment } } + val sd = res.preparedPayment.submissionDate call.respond( PaymentStatus( uuid = res.preparedPayment.id.value, @@ -451,8 +452,10 @@ fun serverMain() { creditorIban = res.preparedPayment.creditorIban, amount = "${res.preparedPayment.sum}:${res.preparedPayment.currency}", subject = res.preparedPayment.subject, - submissionDate = DateTime(res.preparedPayment.submissionDate).toDashedDate(), - preparationDate = DateTime(res.preparedPayment.preparationDate).toDashedDate() + submissionDate = if (sd != null) { + importDateFromMillis(sd).toDashedDate() + } else null, + preparationDate = importDateFromMillis(res.preparedPayment.preparationDate).toDashedDate() ) ) return@get @@ -556,8 +559,8 @@ fun serverMain() { RawBankTransactionEntity.find { (RawBankTransactionsTable.bankAccount eq bankAccount) and RawBankTransactionsTable.bookingDate.between( - parseDashedDate(start ?: "1970-01-01").millis, - parseDashedDate(end ?: DateTime.now().toDashedDate()).millis + parseDashedDate(start ?: "1970-01-01").millis(), + parseDashedDate(end ?: LocalDateTime.now().toDashedDate()).millis() ) }.forEach { ret.transactions.add( @@ -566,7 +569,7 @@ fun serverMain() { counterpartBic = it.counterpartBic, counterpartIban = it.counterpartIban, counterpartName = it.counterpartName, - date = DateTime(it.bookingDate).toDashedDate(), + date = importDateFromMillis(it.bookingDate).toDashedDate(), subject = it.unstructuredRemittanceInformation, amount = "${it.currency}:${it.amount}" ) diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt @@ -51,11 +51,11 @@ import javax.sql.rowset.serial.SerialBlob import javax.xml.datatype.DatatypeFactory import org.apache.commons.compress.utils.IOUtils import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq -import org.joda.time.DateTime -import org.joda.time.Instant import java.io.BufferedInputStream import java.io.ByteArrayInputStream import java.nio.charset.Charset +import java.time.Instant +import java.time.LocalDateTime import java.time.ZoneId import java.time.ZonedDateTime import java.time.format.DateTimeFormatter @@ -163,8 +163,8 @@ fun buildCamtString(type: Int, history: MutableList<RawPayment>): MutableList<St */ val ret = mutableListOf<String>() history.forEach { - val dashedDate = DateTime.parse(it.date).toDashedDate() - val zonedDateTime = DateTime.now().toZonedString() + val dashedDate = expectNonNull(it.date) + val zonedDateTime = LocalDateTime.now().toZonedString() ret.add( constructXml(indent = true) { root("Document") { @@ -405,9 +405,12 @@ private fun constructCamtResponse( ): MutableList<String> { val dateRange = (header.static.orderDetails?.orderParams as EbicsRequest.StandardOrderParams).dateRange - val (start: DateTime, end: DateTime) = if (dateRange != null) { - Pair(DateTime(dateRange.start.toGregorianCalendar().time), DateTime(dateRange.end.toGregorianCalendar().time)) - } else Pair(parseDashedDate("1970-01-01"), DateTime.now()) + val (start: LocalDateTime, end: LocalDateTime) = if (dateRange != null) { + Pair( + importDateFromMillis(dateRange.start.toGregorianCalendar().timeInMillis), + importDateFromMillis(dateRange.end.toGregorianCalendar().timeInMillis) + ) + } else Pair(parseDashedDate("1970-01-01"), LocalDateTime.now()) val history = mutableListOf<RawPayment>() val bankAccount = getBankAccountFromSubscriber(subscriber) transaction { @@ -423,7 +426,7 @@ private fun constructCamtResponse( subject = it.subject, creditorIban = it.creditorIban, debitorIban = it.debitorIban, - date = DateTime(it.date).toDashedDate(), + date = importDateFromMillis(it.date).toDashedDate(), amount = it.amount ) ) @@ -464,7 +467,7 @@ private fun handleCct(paymentRequest: String) { /** For now, the date discards any * information about hours and minor units of time. */ - this.date = parseDashedDate(DateTime.now().toDashedDate()).millis + this.date = Instant.now().toEpochMilli() } } } diff --git a/util/src/main/kotlin/time.kt b/util/src/main/kotlin/time.kt @@ -1,23 +1,31 @@ package tech.libeufin.util -import org.joda.time.DateTime -import org.joda.time.format.DateTimeFormat -import java.time.ZoneId -import java.time.ZonedDateTime +import java.time.* import java.time.format.DateTimeFormatter -fun DateTime.toZonedString(): String { +fun LocalDateTime.toZonedString(): String { val dateFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME - val instant = java.time.Instant.ofEpochMilli(this.millis) - val zoned = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()) - return dateFormatter.format(zoned) + return dateFormatter.format(this.atZone(ZoneId.systemDefault())) } -fun DateTime.toDashedDate(): String { - return this.toString("y-MM-d") +fun LocalDateTime.toDashedDate(): String { + val dtf = DateTimeFormatter.ISO_LOCAL_DATE + return dtf.format(this) } -fun parseDashedDate(date: String): DateTime { - logger.debug("Parsing date: $date") - return DateTime.parse(date, DateTimeFormat.forPattern("y-M-d")) +fun parseDashedDate(date: String): LocalDateTime { + val dtf = DateTimeFormatter.ISO_LOCAL_DATE + return LocalDateTime.from(LocalDate.parse(date, dtf)) } + +fun importDateFromMillis(millis: Long): LocalDateTime { + return LocalDateTime.ofInstant( + Instant.ofEpochMilli(millis), + ZoneId.systemDefault() + ) +} + +fun LocalDateTime.millis(): Long { + val instant = Instant.from(this) + return instant.toEpochMilli() +} +\ No newline at end of file