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) + } +}