diff --git a/common/utils/src/main/kotlin/com/sangdol/common/utils/KoreaDateTimeExtensions.kt b/common/utils/src/main/kotlin/com/sangdol/common/utils/KoreaDateTimeExtensions.kt index 770e8581..b993081b 100644 --- a/common/utils/src/main/kotlin/com/sangdol/common/utils/KoreaDateTimeExtensions.kt +++ b/common/utils/src/main/kotlin/com/sangdol/common/utils/KoreaDateTimeExtensions.kt @@ -15,6 +15,7 @@ object KoreaTime { object KoreaDateTime { fun now(): LocalDateTime = LocalDateTime.now(KST_CLOCK) + fun nowWithOffset(): OffsetDateTime = OffsetDateTime.now(KST_CLOCK) } fun Instant.toKoreaDateTime(): LocalDateTime = this.atZone(KST_CLOCK.zone).toLocalDateTime() diff --git a/common/utils/src/test/kotlin/com/sangdol/common/utils/KoreaDateTimeExtensions.kt b/common/utils/src/test/kotlin/com/sangdol/common/utils/KoreaDateTimeExtensionsTest.kt similarity index 61% rename from common/utils/src/test/kotlin/com/sangdol/common/utils/KoreaDateTimeExtensions.kt rename to common/utils/src/test/kotlin/com/sangdol/common/utils/KoreaDateTimeExtensionsTest.kt index 01ef215e..e6f9a3c6 100644 --- a/common/utils/src/test/kotlin/com/sangdol/common/utils/KoreaDateTimeExtensions.kt +++ b/common/utils/src/test/kotlin/com/sangdol/common/utils/KoreaDateTimeExtensionsTest.kt @@ -3,12 +3,9 @@ package com.sangdol.common.utils import io.kotest.assertions.assertSoftly import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe -import java.time.Instant -import java.time.LocalDateTime -import java.time.LocalTime -import java.time.ZoneId +import java.time.* -class KoreaDateTimeExtensions : FunSpec({ +class KoreaDateTimeExtensionsTest : FunSpec({ test("한국 시간 기준으로 현재 시간을 가져오며, 초 단위는 제외한다.") { assertSoftly(KoreaTime.now()) { @@ -21,7 +18,7 @@ class KoreaDateTimeExtensions : FunSpec({ } } - test("한국 시간 기준으로 현재 날짜 + 시간을 가져온다.") { + test("한국 시간 기준으로 현재 날짜 + 시간을 LocalDateTime 타입으로 가져온다.") { assertSoftly(KoreaDateTime.now()) { val utcNow = LocalDateTime.now(ZoneId.of("UTC")) @@ -29,7 +26,15 @@ class KoreaDateTimeExtensions : FunSpec({ } } - test("UTC 시간을 한국 시간으로 변환한다.") { + test("한국 시간 기준으로 현재 날짜 + 시간을 OffsetDateTime 타입으로 가져온다.") { + assertSoftly(KoreaDateTime.nowWithOffset()) { + val utcNow = OffsetDateTime.now(ZoneId.of("UTC")) + + this.toLocalDateTime().withSecond(0).withNano(0) shouldBe utcNow.toLocalDateTime().plusHours(9).withSecond(0).withNano(0) + } + } + + test("UTC 시간을 LocalDateTime 타입의 한국 시간으로 변환한다.") { val now = Instant.now() val kstConverted = now.toKoreaDateTime() val utc = now.atZone(ZoneId.of("UTC")).toLocalDateTime() diff --git a/common/web/src/main/kotlin/com/sangdol/common/web/config/JacksonConfig.kt b/common/web/src/main/kotlin/com/sangdol/common/web/config/JacksonConfig.kt index fb6eb907..bede0de2 100644 --- a/common/web/src/main/kotlin/com/sangdol/common/web/config/JacksonConfig.kt +++ b/common/web/src/main/kotlin/com/sangdol/common/web/config/JacksonConfig.kt @@ -87,4 +87,4 @@ class JacksonConfig { gen.writeString(value.format(ISO_OFFSET_DATE_TIME_FORMATTER)) } } -} \ No newline at end of file +} diff --git a/service/src/test/kotlin/com/sangdol/data/DefaultDataInitializer.kt b/service/src/test/kotlin/com/sangdol/data/DefaultDataInitializer.kt index 345ea14e..9c6b7d24 100644 --- a/service/src/test/kotlin/com/sangdol/data/DefaultDataInitializer.kt +++ b/service/src/test/kotlin/com/sangdol/data/DefaultDataInitializer.kt @@ -2,6 +2,7 @@ package com.sangdol.data import com.sangdol.common.persistence.IDGenerator import com.sangdol.common.persistence.TransactionExecutionUtil +import com.sangdol.common.utils.KoreaDateTime import com.sangdol.roomescape.admin.infrastructure.persistence.AdminEntity import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType @@ -629,8 +630,8 @@ data class PaymentWithMethods( class PaymentDataInitializer : AbstractDataInitializer() { companion object { - val requestedAtCache: Timestamp = Timestamp.valueOf(OffsetDateTime.now().toLocalDateTime()) - val approvedAtCache: Timestamp = Timestamp.valueOf(OffsetDateTime.now().plusSeconds(5).toLocalDateTime()) + val requestedAtCache: Timestamp = Timestamp.valueOf(KoreaDateTime.nowWithOffset().toLocalDateTime()) + val approvedAtCache: Timestamp = Timestamp.valueOf(KoreaDateTime.nowWithOffset().plusSeconds(5).toLocalDateTime()) val supportedPaymentMethods = listOf(PaymentMethod.TRANSFER, PaymentMethod.EASY_PAY, PaymentMethod.CARD) val supportedCardType = listOf(CardType.CREDIT, CardType.CHECK) diff --git a/service/src/test/kotlin/com/sangdol/roomescape/payment/SampleTosspayConstant.kt b/service/src/test/kotlin/com/sangdol/roomescape/payment/SampleTosspayConstant.kt index aa1c8514..b75bb0d7 100644 --- a/service/src/test/kotlin/com/sangdol/roomescape/payment/SampleTosspayConstant.kt +++ b/service/src/test/kotlin/com/sangdol/roomescape/payment/SampleTosspayConstant.kt @@ -1,5 +1,6 @@ package com.sangdol.roomescape.payment +import com.sangdol.common.utils.KoreaDateTime import java.time.OffsetDateTime object SampleTosspayConstant { @@ -39,8 +40,8 @@ object SampleTosspayConstant { "orderName": "Sonya Aguirre 예약 결제", "taxExemptionAmount": 0, "status": "DONE", - "requestedAt": "${OffsetDateTime.now()}", - "approvedAt": "${OffsetDateTime.now().plusSeconds(5)}", + "requestedAt": "${KoreaDateTime.nowWithOffset()}", + "approvedAt": "${KoreaDateTime.nowWithOffset().plusSeconds(5)}", "useEscrow": false, "cultureExpense": false, "card": { @@ -102,8 +103,8 @@ object SampleTosspayConstant { "orderName": "Sonya Aguirre 예약 결제", "taxExemptionAmount": 0, "status": "CANCELED", - "requestedAt": "${OffsetDateTime.now()}", - "approvedAt": "${OffsetDateTime.now().plusSeconds(5)}", + "requestedAt": "${KoreaDateTime.nowWithOffset()}", + "approvedAt": "${KoreaDateTime.nowWithOffset().plusSeconds(5)}", "useEscrow": false, "cultureExpense": false, "card": { @@ -132,7 +133,7 @@ object SampleTosspayConstant { "transactionKey": "txrd_a01k4mtgh26vgrn1evbdckyqmdr", "cancelReason": "$CANCEL_REASON", "taxExemptionAmount": 0, - "canceledAt": "${OffsetDateTime.now().plusMinutes(1)}", + "canceledAt": "${KoreaDateTime.nowWithOffset().plusMinutes(1)}", "cardDiscountAmount": 0, "transferDiscountAmount": 0, "easyPayDiscountAmount": 0, @@ -181,8 +182,8 @@ object SampleTosspayConstant { "orderName": "Sonya Aguirre 예약 결제", "taxExemptionAmount": 0, "status": "DONE", - "requestedAt": "${OffsetDateTime.now()}", - "approvedAt": "${OffsetDateTime.now().plusSeconds(5)}", + "requestedAt": "${KoreaDateTime.nowWithOffset()}", + "approvedAt": "${KoreaDateTime.nowWithOffset().plusSeconds(5)}", "useEscrow": false, "cultureExpense": false, "card": null, @@ -230,8 +231,8 @@ object SampleTosspayConstant { "orderName": "Sonya Aguirre 예약 결제", "taxExemptionAmount": 0, "status": "DONE", - "requestedAt": "${OffsetDateTime.now()}", - "approvedAt": "${OffsetDateTime.now().plusSeconds(5)}", + "requestedAt": "${KoreaDateTime.nowWithOffset()}", + "approvedAt": "${KoreaDateTime.nowWithOffset().plusSeconds(5)}", "useEscrow": false, "cultureExpense": false, "card": null, @@ -250,7 +251,7 @@ object SampleTosspayConstant { "transactionKey": "txrd_a01k4mtgh26vgrn1evbdckyqmdr", "cancelReason": "$CANCEL_REASON", "taxExemptionAmount": 0, - "canceledAt": "${OffsetDateTime.now().plusMinutes(1)}", + "canceledAt": "${KoreaDateTime.nowWithOffset().plusMinutes(1)}", "cardDiscountAmount": 0, "transferDiscountAmount": 0, "easyPayDiscountAmount": 0, diff --git a/service/src/test/kotlin/com/sangdol/roomescape/supports/Fixtures.kt b/service/src/test/kotlin/com/sangdol/roomescape/supports/Fixtures.kt index bf59d52b..3833b24c 100644 --- a/service/src/test/kotlin/com/sangdol/roomescape/supports/Fixtures.kt +++ b/service/src/test/kotlin/com/sangdol/roomescape/supports/Fixtures.kt @@ -2,6 +2,7 @@ package com.sangdol.roomescape.supports import com.github.f4b6a3.tsid.TsidFactory import com.sangdol.common.persistence.TsidIDGenerator +import com.sangdol.common.utils.KoreaDateTime import com.sangdol.roomescape.admin.infrastructure.persistence.AdminEntity import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType @@ -297,8 +298,8 @@ object PaymentFixture { card = cardDetail, easyPay = easyPayDetail, transfer = transferDetail, - requestedAt = OffsetDateTime.now(), - approvedAt = OffsetDateTime.now().plusSeconds(5) + requestedAt = KoreaDateTime.nowWithOffset(), + approvedAt = KoreaDateTime.nowWithOffset().plusSeconds(5) ) fun cancelResponse( @@ -314,7 +315,7 @@ object PaymentFixture { cardDiscountAmount = cardDiscountAmount, transferDiscountAmount = transferDiscountAmount, easyPayDiscountAmount = easypayDiscountAmount, - canceledAt = OffsetDateTime.now().plusSeconds(5), + canceledAt = KoreaDateTime.nowWithOffset().plusSeconds(5), cancelReason = cancelReason ), ) diff --git a/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/business/domain/Payment.kt b/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/business/domain/Payment.kt index 004b66c6..a9bc013e 100644 --- a/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/business/domain/Payment.kt +++ b/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/business/domain/Payment.kt @@ -1,5 +1,6 @@ package com.sangdol.tosspaymock.business.domain +import com.sangdol.common.utils.KoreaDateTime import com.sangdol.tosspaymock.business.domain.cancel.Cancellation import com.sangdol.tosspaymock.business.domain.card.Card import com.sangdol.tosspaymock.business.domain.easypay.Easypay @@ -128,7 +129,7 @@ class Payment( return create( paymentKey = paymentKey, orderId = "orderId", - requestedAt = OffsetDateTime.now(), + requestedAt = KoreaDateTime.nowWithOffset(), amount = cancellation.cancelAmount, card = null, easyPay = null, @@ -165,7 +166,7 @@ class Payment( orderId = orderId, orderName = "테스트 결제", requestedAt = requestedAt, - approvedAt = OffsetDateTime.now(), + approvedAt = KoreaDateTime.nowWithOffset(), card = card, easyPay = easyPay, transfer = bankTransfer, diff --git a/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/business/domain/cancel/Cancellation.kt b/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/business/domain/cancel/Cancellation.kt index edd2e389..a237ec89 100644 --- a/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/business/domain/cancel/Cancellation.kt +++ b/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/business/domain/cancel/Cancellation.kt @@ -1,5 +1,6 @@ package com.sangdol.tosspaymock.business.domain.cancel +import com.sangdol.common.utils.KoreaDateTime import com.sangdol.tosspaymock.business.domain.RandomPaymentValueGenerator import com.sangdol.tosspaymock.web.dto.CancelResponse import java.time.OffsetDateTime @@ -29,7 +30,7 @@ class Cancellation( ) = Cancellation( transactionKey = RandomPaymentValueGenerator.transactionKey(), cancelReason = cancelReason, - canceledAt = OffsetDateTime.now(), + canceledAt = KoreaDateTime.nowWithOffset(), cardDiscountAmount = cardDiscountAmount, transferDiscountAmount = transferDiscountAmount, easyPayDiscountAmount = easyPayDiscountAmount, diff --git a/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/web/dto/TosspayRequest.kt b/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/web/dto/TosspayRequest.kt index e38cf0eb..3d4b7df1 100644 --- a/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/web/dto/TosspayRequest.kt +++ b/tosspay-mock/src/main/kotlin/com/sangdol/tosspaymock/web/dto/TosspayRequest.kt @@ -1,12 +1,13 @@ package com.sangdol.tosspaymock.web.dto +import com.sangdol.common.utils.KoreaDateTime import java.time.OffsetDateTime data class PaymentConfirmRequest( val paymentKey: String, val orderId: String, val amount: Int, - val requestedAt: OffsetDateTime = OffsetDateTime.now() + val requestedAt: OffsetDateTime = KoreaDateTime.nowWithOffset() ) data class PaymentCancelRequest(