diff --git a/docs/20260303_기부목록조회월범위한국시간수정.md b/docs/20260303_기부목록조회월범위한국시간수정.md index cb926b1d..bbee9fb6 100644 --- a/docs/20260303_기부목록조회월범위한국시간수정.md +++ b/docs/20260303_기부목록조회월범위한국시간수정.md @@ -2,8 +2,10 @@ ## 구현 항목 - [x] `ChannelDonationService.kt`의 `getChannelDonationList` 내 조회 범위 수정 - - 현재 UTC 기준을 한국 시간(KST) 기준으로 변경 - - 해당월 1일 00:00:00(KST) ~ 다음달 1일 00:00:00(KST) + - UTC 현재 시각을 기준으로 한국 시간(KST) 월 경계를 계산 + - KST 월 경계(해당월 1일 00:00:00 ~ 다음달 1일 00:00:00)를 UTC 조회 구간으로 변환 +- [x] 채널 후원 조회 UTC 전달값 검증 테스트 보강 + - `ChannelDonationServiceTest`에서 전달된 UTC 범위를 KST로 역변환했을 때 월 경계가 유지되는지 검증 ## 검증 결과 ### 1차 구현 @@ -21,3 +23,19 @@ ``` - 결과: 기존 단위 테스트(`ChannelDonationServiceTest`) 4건 모두 통과 확인. - `./gradlew test --tests kr.co.vividnext.sodalive.explorer.profile.channelDonation.ChannelDonationServiceTest` 실행 결과 성공. + +### 2차 수정 +- 무엇을: `getChannelDonationList`에서 월 조회 시작/종료 시각을 KST 기준으로 계산한 뒤 UTC `LocalDateTime`으로 변환해 repository에 전달하도록 수정 +- 왜: KST 타임존만 적용하고 조회 파라미터를 UTC로 변환하지 않으면 조회 날짜가 기존과 동일하게 남아 월 경계가 의도대로 이동하지 않음 +- 어떻게: + - `ChannelDonationService.kt` + - `ZonedDateTime.now(ZoneId.of("UTC"))`로 현재 시각을 얻고 `withZoneSameInstant(ZoneId.of("Asia/Seoul"))`로 KST 변환 + - KST 월 시작/종료(`startDateTimeKst`, `endDateTimeKst`)를 각각 UTC로 변환해 `startDateTime`, `endDateTime` 생성 + - `ChannelDonationServiceTest.kt` + - 캡처한 UTC 조회 파라미터를 KST로 역변환해 `1일 00:00:00` 및 `+1개월` 월 경계를 검증하도록 수정 + - 정적 진단: `lsp_diagnostics` 실행 시 `.kt` 확장자 LSP 미구성으로 진단 불가(환경 제약) + - 검증 명령: + - `./gradlew test --tests "kr.co.vividnext.sodalive.explorer.profile.channelDonation.*"` 실행: 성공 + - `./gradlew build` 실행: 성공 + - `./gradlew tasks --all` 실행: 성공 +- 결과: KST 월 경계가 UTC 조회 구간으로 반영되어 예시와 같은 형태(예: 2026-03-01 00:00:00 KST → 2026-02-28 15:00:00 UTC 시작)로 조회 조건이 구성됨 diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/channelDonation/ChannelDonationService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/channelDonation/ChannelDonationService.kt index d6a48a16..b6727496 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/channelDonation/ChannelDonationService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/explorer/profile/channelDonation/ChannelDonationService.kt @@ -63,13 +63,23 @@ class ChannelDonationService( memberRepository.findCreatorByIdOrNull(creatorId) ?: throw SodaException(messageKey = "member.validation.creator_not_found") + val utcZoneId = ZoneId.of("UTC") val kstZoneId = ZoneId.of("Asia/Seoul") - val nowKst = ZonedDateTime.now(kstZoneId) - val startDateTime = nowKst + val nowUtc = ZonedDateTime.now(utcZoneId) + val nowKst = nowUtc.withZoneSameInstant(kstZoneId) + + val startDateTimeKst = nowKst .with(TemporalAdjusters.firstDayOfMonth()) .toLocalDate() - .atStartOfDay() - val endDateTime = startDateTime.plusMonths(1) + .atStartOfDay(kstZoneId) + val endDateTimeKst = startDateTimeKst.plusMonths(1) + + val startDateTime = startDateTimeKst + .withZoneSameInstant(utcZoneId) + .toLocalDateTime() + val endDateTime = endDateTimeKst + .withZoneSameInstant(utcZoneId) + .toLocalDateTime() val isCreator = member.role == MemberRole.CREATOR && creatorId == member.id val totalCount = channelDonationMessageRepository.getChannelDonationMessageTotalCount( diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/explorer/profile/channelDonation/ChannelDonationServiceTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/explorer/profile/channelDonation/ChannelDonationServiceTest.kt index 0748a811..6e98ced2 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/explorer/profile/channelDonation/ChannelDonationServiceTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/explorer/profile/channelDonation/ChannelDonationServiceTest.kt @@ -15,6 +15,7 @@ import org.junit.jupiter.api.Test import org.mockito.Mockito import java.time.LocalDateTime import java.time.LocalTime +import java.time.ZoneId class ChannelDonationServiceTest { private lateinit var canPaymentService: CanPaymentService @@ -132,9 +133,20 @@ class ChannelDonationServiceTest { ) // then: 월 시작/다음 달 시작 범위를 사용해야 한다. - assertEquals(1, capturedStartDateTime!!.dayOfMonth) - assertEquals(LocalTime.MIDNIGHT, capturedStartDateTime!!.toLocalTime()) - assertEquals(capturedStartDateTime!!.plusMonths(1), capturedEndDateTime) + val utcZoneId = ZoneId.of("UTC") + val kstZoneId = ZoneId.of("Asia/Seoul") + val startDateTimeKst = capturedStartDateTime!! + .atZone(utcZoneId) + .withZoneSameInstant(kstZoneId) + .toLocalDateTime() + val endDateTimeKst = capturedEndDateTime!! + .atZone(utcZoneId) + .withZoneSameInstant(kstZoneId) + .toLocalDateTime() + + assertEquals(1, startDateTimeKst.dayOfMonth) + assertEquals(LocalTime.MIDNIGHT, startDateTimeKst.toLocalTime()) + assertEquals(startDateTimeKst.plusMonths(1), endDateTimeKst) } @Test @@ -246,9 +258,20 @@ class ChannelDonationServiceTest { ) // then: 월 시작/다음 달 시작 범위를 사용해야 한다. - assertEquals(1, capturedStartDateTime!!.dayOfMonth) - assertEquals(LocalTime.MIDNIGHT, capturedStartDateTime!!.toLocalTime()) - assertEquals(capturedStartDateTime!!.plusMonths(1), capturedEndDateTime) + val utcZoneId = ZoneId.of("UTC") + val kstZoneId = ZoneId.of("Asia/Seoul") + val startDateTimeKst = capturedStartDateTime!! + .atZone(utcZoneId) + .withZoneSameInstant(kstZoneId) + .toLocalDateTime() + val endDateTimeKst = capturedEndDateTime!! + .atZone(utcZoneId) + .withZoneSameInstant(kstZoneId) + .toLocalDateTime() + + assertEquals(1, startDateTimeKst.dayOfMonth) + assertEquals(LocalTime.MIDNIGHT, startDateTimeKst.toLocalTime()) + assertEquals(startDateTimeKst.plusMonths(1), endDateTimeKst) } private fun createMember(id: Long, role: MemberRole, nickname: String): Member {