-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] 알람 로직 리팩토링 및 테스트 코드 추가 #233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 31 commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
bdbf213
[UI/#226] OrbitPicker 사이즈 축소
DongChyeon 3705c85
[UI/#226] 미션 선택 섹션 추가
DongChyeon 0d281bd
[REFACTOR/#226] Type 안정성과 재사용성을 위해 PickeState를 generic으로 처리
DongChyeon 1b3a951
[FEAT/#226] 미션 종류에 없음 추가
DongChyeon e6b9872
[REMOVE/#226] JUnit4를 사용하므로 useJUnitPlatform 제거
DongChyeon 7474871
[FEAT/#226] AlarmEntity isAm 컬럼 제거
DongChyeon 153cca5
[FEAT/#226] OrbitPicker가 java.time.LocalTime을 사용하도록 수정
DongChyeon aa761ec
[FEAT/#226] 알람 시간 표현을 LocalTime으로 통일
DongChyeon 1826d1e
[FEAT/#226] 미션 타입이 NONE일 때 처리 추가
DongChyeon 5c58962
[REMOVE/#226] 사용하지 않는 DB 연산 제거
DongChyeon ec9ab8b
[FEAT/#226] AlarmDateTimeFormatter에 알람 시간 계산 로직 위임
DongChyeon 790faf6
[TEST/#226] AlarmDateTimeFormatter 테스트 코드 추가
DongChyeon 2fcbf39
[REFACTOR/#226] AlarmScheduler를 UseCase를 통해 사용하도록 변경
DongChyeon b258571
[REFACTOR/#226] 알람 시간 계산 로직을 AlarmTimeCalculator로 분리
DongChyeon a68c962
[FIX/#226] 알람 스케줄링 시 공휴일 건너뛰기 여부에 따라 건너뛰도록 수정
DongChyeon d28a2ef
[TEST/#226] AlarmTimeCalculator 테스트 코드 추가
DongChyeon 5587818
[FEAT/#226] AlarmEntity 관련 매핑 함수에 missionType과 missionCount 필드 추가
DongChyeon e3eea36
[FEAT/#226] MIGRATION_1_2 로직에 isAm 컬럼에 따른 시간 변환 로직 추가
DongChyeon 955f467
[REFACTOR/#226] AlarmDateTimeFormatter 상수 정의 및 로그 제거
DongChyeon 28d7e10
[FEAT/#226] 데이터베이스 마이그레이션 로직에 롤백 보장을 위한 트랜잭션 적용
DongChyeon 05f5150
[TEST/#226] 12시간제에서 24시간제로 시간 변환 검증 테스트 추가
DongChyeon 152b993
[REFACTOR/#226] 반복 알람 요일이 비어있을 경우 예외 발생하도록 검증 로직 변경
DongChyeon f392798
[REFACTOR/#226] 반복 알람 로직에서 잘못된 fallback 제거 및 명시적 예외 처리
DongChyeon bb9f921
[TEST/#226] AlarmDateTimeFormatterTest에 Clock 주입 적용하여 CI 환경 시간 오류 방지
DongChyeon a72dfae
[FIX/#226] ClockModule 생성 및 의존성 주입
DongChyeon 8bbaea0
[REFACTOR/#226] AlarmDateTimeFormatter :feature:home 모듈로 이전
DongChyeon b114a1d
[MOVE/#226] 홈 모듈 내 알람 관련 파일 com.yapp.alarm 패키지로 이동
DongChyeon ecb5d2a
[MOVE/#226] ClockModule을 common 모듈로 이동
DongChyeon acf0c82
[TEST/#226] AlarmDateTimeFormatter 테스트용 Locale 사용
DongChyeon fc1702b
[FEAT/#226] AlarmDateTimeFormatter 예외 발생 시 로그 추가
DongChyeon 06107dd
[REFACTOR/#226] formatTimeDifference 중복 검사 로직 제거
DongChyeon 36bcb48
[FEAT/#226] AlarmDateTimeFormatter 테스트 용이성을 위한 Locale 주입
DongChyeon 57d2da9
[FEAT/#226] 의존성 그래프 모듈 유형별 색상 구분
DongChyeon c5f3202
[REFACTOR/#226] given/when/then 분리
DongChyeon 8ce6247
[CHORE/#227] Jacoco 리포트를 Codecov에 업로드하도록 수정
MoonsuKang d9cb6aa
[ADD/#227] Jacoco XML 리포트 생성 활성화
MoonsuKang 1b958ab
[MOD/#227] CI 워크플로우에 Codecov 토큰 추가
MoonsuKang 6a56222
[ADD/#227] Codecov 설정 파일 추가
MoonsuKang 1f10398
[MOD/#227] 커버리지 리포트 PR 자동 코멘트 기능 삭제
MoonsuKang f63bce9
[FEAT/#226] MigrationTest에서 db를 닫기 위해 close 호출
DongChyeon d38d230
[REFACTOR/#226] AlarmDateTimeFormatter 코드 가독성 개선
DongChyeon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
core/alarm/src/main/java/com/yapp/alarm/AlarmTimeCalculator.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| package com.yapp.alarm | ||
|
|
||
| import com.yapp.domain.model.Alarm | ||
| import com.yapp.domain.model.AlarmDay | ||
| import com.yapp.domain.model.toDayOfWeek | ||
| import java.time.Clock | ||
| import java.time.LocalDateTime | ||
| import java.time.ZoneId | ||
| import java.time.format.DateTimeFormatter | ||
| import javax.inject.Inject | ||
|
|
||
| class AlarmTimeCalculator @Inject constructor( | ||
| private val clock: Clock, | ||
| ) { | ||
| private val holidayDateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") | ||
|
|
||
| private fun isHoliday(dateToCheck: LocalDateTime): Boolean { | ||
| if (dateToCheck.year == 2025) { | ||
| val dateString = dateToCheck.format(holidayDateFormatter) | ||
| return AlarmConstants.HOLIDAYS_2025.contains(dateString) | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| private fun skipHolidaysIfEnabled(initialDateTime: LocalDateTime, alarm: Alarm): LocalDateTime { | ||
| if (!alarm.isHolidayAlarmOff) return initialDateTime | ||
|
|
||
| var adjustedDateTime = initialDateTime | ||
| while (isHoliday(adjustedDateTime)) { | ||
| adjustedDateTime = adjustedDateTime.plusWeeks(1) | ||
| } | ||
|
|
||
| return adjustedDateTime | ||
| } | ||
DongChyeon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| private fun getAlarmDateTimeOnDate(alarm: Alarm, now: LocalDateTime): LocalDateTime { | ||
| return now | ||
| .withHour(alarm.hour) | ||
| .withMinute(alarm.minute) | ||
| .withSecond(alarm.second) | ||
| .withNano(0) | ||
| } | ||
|
|
||
| fun calculateNextRepeatingTimeMillis( | ||
| alarm: Alarm, | ||
| alarmDay: AlarmDay, | ||
| zoneId: ZoneId = clock.zone, | ||
| ): Long { | ||
| val now = LocalDateTime.now(clock) | ||
| val targetDayOfWeek = alarmDay.toDayOfWeek() | ||
|
|
||
| val alarmDateTimeToday = getAlarmDateTimeOnDate(alarm, now) | ||
|
|
||
| var nextAlarmDateTimeCandidate = alarmDateTimeToday | ||
|
|
||
| while (nextAlarmDateTimeCandidate.dayOfWeek != targetDayOfWeek || nextAlarmDateTimeCandidate.isBefore(now)) { | ||
| nextAlarmDateTimeCandidate = nextAlarmDateTimeCandidate.plusDays(1) | ||
| } | ||
|
|
||
| nextAlarmDateTimeCandidate = skipHolidaysIfEnabled(nextAlarmDateTimeCandidate, alarm) | ||
|
|
||
| return nextAlarmDateTimeCandidate.atZone(zoneId).toInstant().toEpochMilli() | ||
| } | ||
|
|
||
| fun calculateNonRepeatingTimeMillis( | ||
| alarm: Alarm, | ||
| zoneId: ZoneId = clock.zone, | ||
| ): Long { | ||
| val now = LocalDateTime.now(clock) | ||
| var alarmDateTime = getAlarmDateTimeOnDate(alarm, now) | ||
|
|
||
| if (alarmDateTime.isBefore(now)) { | ||
| alarmDateTime = alarmDateTime.plusDays(1) | ||
| } | ||
|
|
||
| return alarmDateTime.atZone(zoneId).toInstant().toEpochMilli() | ||
| } | ||
|
|
||
| fun calculateNextWeeklyRescheduledTimeMillis( | ||
| alarm: Alarm, | ||
| alarmTargetDay: AlarmDay, | ||
| zoneId: ZoneId = clock.zone, | ||
| ): Long { | ||
| val now = LocalDateTime.now(clock) | ||
| val targetDayOfWeek = alarmTargetDay.toDayOfWeek() | ||
|
|
||
| var initialAlarmDateTimeCandidate = getAlarmDateTimeOnDate(alarm, now) | ||
|
|
||
| while (initialAlarmDateTimeCandidate.dayOfWeek != targetDayOfWeek || initialAlarmDateTimeCandidate.isBefore(now)) { | ||
| initialAlarmDateTimeCandidate = initialAlarmDateTimeCandidate.plusDays(1) | ||
| } | ||
|
|
||
| val nextWeeklyAlarmDateTimeCandidate = initialAlarmDateTimeCandidate.plusWeeks(1) | ||
| val nextWeeklyAlarmDateTime = skipHolidaysIfEnabled(nextWeeklyAlarmDateTimeCandidate, alarm) | ||
|
|
||
| return nextWeeklyAlarmDateTime.atZone(zoneId).toInstant().toEpochMilli() | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.