From eb4df66ece8f8d6bf1438b17908c60c4fa08cc36 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 10 Jul 2026 03:20:20 +0900 Subject: [PATCH] =?UTF-8?q?feat(home):=20AI=20=EC=BA=90=EB=A6=AD=ED=84=B0?= =?UTF-8?q?=20=EC=8A=A4=EB=83=85=EC=83=B7=20=EC=A7=91=EA=B3=84=20=EA=B8=B0?= =?UTF-8?q?=EA=B0=84=EC=9D=84=20=EC=A0=95=EC=9D=98=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RecommendationSnapshotWindowPolicy.kt | 41 +++++++++++++++++++ .../RecommendationSnapshotWindowPolicyTest.kt | 20 +++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/v2/recommendation/domain/RecommendationSnapshotWindowPolicy.kt create mode 100644 src/test/kotlin/kr/co/vividnext/sodalive/v2/recommendation/domain/RecommendationSnapshotWindowPolicyTest.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/recommendation/domain/RecommendationSnapshotWindowPolicy.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/recommendation/domain/RecommendationSnapshotWindowPolicy.kt new file mode 100644 index 00000000..bdd9dd13 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/recommendation/domain/RecommendationSnapshotWindowPolicy.kt @@ -0,0 +1,41 @@ +package kr.co.vividnext.sodalive.v2.recommendation.domain + +import java.time.LocalDateTime +import java.time.ZoneId + +class RecommendationSnapshotWindowPolicy { + fun previousKstDayUtcWindow(nowUtc: LocalDateTime): RecommendationSnapshotWindow { + val previousKstDate = nowUtc + .atZone(UTC_ZONE) + .withZoneSameInstant(KST_ZONE) + .toLocalDate() + .minusDays(1) + val startUtc = previousKstDate + .atStartOfDay(KST_ZONE) + .withZoneSameInstant(UTC_ZONE) + .toLocalDateTime() + val endExclusiveUtc = previousKstDate + .plusDays(1) + .atStartOfDay(KST_ZONE) + .withZoneSameInstant(UTC_ZONE) + .toLocalDateTime() + val snapshotAt = endExclusiveUtc.minusSeconds(1) + + return RecommendationSnapshotWindow( + startUtc = startUtc, + endExclusiveUtc = endExclusiveUtc, + snapshotAt = snapshotAt + ) + } + + companion object { + private val UTC_ZONE: ZoneId = ZoneId.of("UTC") + private val KST_ZONE: ZoneId = ZoneId.of("Asia/Seoul") + } +} + +data class RecommendationSnapshotWindow( + val startUtc: LocalDateTime, + val endExclusiveUtc: LocalDateTime, + val snapshotAt: LocalDateTime +) diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/recommendation/domain/RecommendationSnapshotWindowPolicyTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/recommendation/domain/RecommendationSnapshotWindowPolicyTest.kt new file mode 100644 index 00000000..a2cefa11 --- /dev/null +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/recommendation/domain/RecommendationSnapshotWindowPolicyTest.kt @@ -0,0 +1,20 @@ +package kr.co.vividnext.sodalive.v2.recommendation.domain + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import java.time.LocalDateTime + +class RecommendationSnapshotWindowPolicyTest { + private val policy = RecommendationSnapshotWindowPolicy() + + @Test + @DisplayName("KST 전날 하루를 UTC 조회 범위로 변환한다") + fun shouldConvertPreviousKstDayToUtcWindow() { + val window = policy.previousKstDayUtcWindow(LocalDateTime.of(2026, 7, 9, 21, 0, 0)) + + assertEquals(LocalDateTime.of(2026, 7, 8, 15, 0, 0), window.startUtc) + assertEquals(LocalDateTime.of(2026, 7, 9, 15, 0, 0), window.endExclusiveUtc) + assertEquals(LocalDateTime.of(2026, 7, 9, 14, 59, 59), window.snapshotAt) + } +}