날짜 체크 수정

This commit is contained in:
2025-03-06 11:59:36 +09:00
parent 8dcfc4ed13
commit ed6e299814

View File

@@ -23,6 +23,8 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashMap;
@@ -135,6 +137,7 @@ public class BattleEventService {
List<BattleEvent> existingList = battleMapper.getCheckBattleEventList(battleEventRequest);
boolean isTime = isTimeOverlapping(existingList, battleEventRequest);
if(isTime){
log.warn("battle Schedule duplication start_dt: {}, end_dt: {}, operation_time: {}", battleEventRequest.getEventStartDt(), battleEventRequest.getEventEndDt(), operation_time);
return BattleEventResponse.builder()
.status(CommonCode.ERROR.getHttpStatus())
.result(ErrorCode.ERROR_BATTLE_EVENT_TIME_OVER.toString())
@@ -363,14 +366,205 @@ public class BattleEventService {
}
private boolean isTimeOverlapping(List<BattleEvent> existingList, BattleEventRequest battleEventRequest){
LocalTime newStartTime = battleEventRequest.getEventStartDt().toLocalTime();
LocalDateTime newStartDt = battleEventRequest.getEventStartDt();
LocalDateTime newEndDt = battleEventRequest.getEventEndDt();
LocalDate newStartDate = newStartDt.toLocalDate();
LocalDate newEndDate = newEndDt.toLocalDate();
LocalTime newStartTime = newStartDt.toLocalTime();
LocalTime newEndTime = newStartTime.plusSeconds(battleEventRequest.getEventOperationTime());
BattleEvent.BATTLE_REPEAT_TYPE newRepeatType = battleEventRequest.getRepeatType();
return existingList.stream().anyMatch(schedule -> {
LocalTime existingStartTime = schedule.getEventStartDt().toLocalTime();
LocalTime existingEndTime = existingStartTime.plusSeconds(schedule.getEventOperationTime());
return existingList.stream().anyMatch(existingEvent -> {
// 자기 자신은 제외 (수정 시)
if (battleEventRequest.getId() != null && battleEventRequest.getId().equals(existingEvent.getId())) {
return false;
}
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
// 기존 이벤트 정보
LocalDateTime existingStartDt = existingEvent.getEventStartDt();
LocalDateTime existingEndDt = existingEvent.getEventEndDt();
LocalDate existingStartDate = existingStartDt.toLocalDate();
LocalDate existingEndDate = existingEndDt.toLocalDate();
LocalTime existingStartTime = existingStartDt.toLocalTime();
LocalTime existingEndTime = existingStartTime.plusSeconds(existingEvent.getEventOperationTime());
BattleEvent.BATTLE_REPEAT_TYPE existingRepeatType = existingEvent.getRepeatType();
// 1. 두 이벤트가 모두 NONE 타입인 경우
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE &&
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE) {
// 같은 날짜인지 확인
if (newStartDate.equals(existingStartDate)) {
// 시간이 겹치는지 확인
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
}
return false;
}
// 2. NONE 타입과 DAY 타입 간의 중복 체크
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE &&
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY) {
// NONE 이벤트의 날짜가 DAY 이벤트의 기간 내에 있는지 확인
if (isDateInRange(newStartDate, existingStartDate, existingEndDate)) {
// 시간이 겹치는지 확인
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
}
return false;
}
// 3. DAY 타입과 NONE 타입 간의 중복 체크
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY &&
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE) {
// NONE 이벤트의 날짜가 DAY 이벤트의 기간 내에 있는지 확인
if (isDateInRange(existingStartDate, newStartDate, newEndDate)) {
// 시간이 겹치는지 확인
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
}
return false;
}
// 4. 두 이벤트가 모두 DAY 타입인 경우
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY &&
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY) {
// 날짜 범위가 겹치는지 확인
if (datesOverlap(newStartDate, newEndDate, existingStartDate, existingEndDate)) {
// 시간이 겹치는지 확인
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
}
return false;
}
// 5. NONE 타입과 요일 타입 간의 중복 체크
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE &&
isWeekdayType(existingRepeatType)) {
// NONE 이벤트의 날짜가 요일 이벤트의 기간 내에 있는지 확인
if (isDateInRange(newStartDate, existingStartDate, existingEndDate)) {
// NONE 이벤트의 요일이 요일 이벤트의 요일과 일치하는지 확인
DayOfWeek noneDayOfWeek = newStartDate.getDayOfWeek();
DayOfWeek weekdayType = getDayOfWeekFromRepeatType(existingRepeatType);
if (noneDayOfWeek == weekdayType) {
// 시간이 겹치는지 확인
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
}
}
return false;
}
// 6. 요일 타입과 NONE 타입 간의 중복 체크
if (isWeekdayType(newRepeatType) &&
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.NONE) {
// NONE 이벤트의 날짜가 요일 이벤트의 기간 내에 있는지 확인
if (isDateInRange(existingStartDate, newStartDate, newEndDate)) {
// NONE 이벤트의 요일이 요일 이벤트의 요일과 일치하는지 확인
DayOfWeek noneDayOfWeek = existingStartDate.getDayOfWeek();
DayOfWeek weekdayType = getDayOfWeekFromRepeatType(newRepeatType);
if (noneDayOfWeek == weekdayType) {
// 시간이 겹치는지 확인
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
}
}
return false;
}
// 7. DAY 타입과 요일 타입 간의 중복 체크
if (newRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY &&
isWeekdayType(existingRepeatType)) {
// 날짜 범위가 겹치는지 확인
if (datesOverlap(newStartDate, newEndDate, existingStartDate, existingEndDate)) {
// 날짜 범위 내에 해당 요일이 적어도 하나 있는지 확인
if (hasOverlappingWeekday(newStartDate, newEndDate, existingStartDate, existingEndDate, getDayOfWeekFromRepeatType(existingRepeatType))) {
// 시간이 겹치는지 확인
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
}
}
return false;
}
// 8. 요일 타입과 DAY 타입 간의 중복 체크
if (isWeekdayType(newRepeatType) &&
existingRepeatType == BattleEvent.BATTLE_REPEAT_TYPE.DAY) {
// 날짜 범위가 겹치는지 확인
if (datesOverlap(newStartDate, newEndDate, existingStartDate, existingEndDate)) {
// 날짜 범위 내에 해당 요일이 적어도 하나 있는지 확인
if (hasOverlappingWeekday(newStartDate, newEndDate, existingStartDate, existingEndDate, getDayOfWeekFromRepeatType(newRepeatType))) {
// 시간이 겹치는지 확인
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
}
}
return false;
}
// 9. 두 이벤트가 모두 요일 타입인 경우
if (isWeekdayType(newRepeatType) && isWeekdayType(existingRepeatType)) {
// 같은 요일인지 확인
if (newRepeatType == existingRepeatType) {
// 날짜 범위가 겹치는지 확인
if (datesOverlap(newStartDate, newEndDate, existingStartDate, existingEndDate)) {
// 시간이 겹치는지 확인
return !existingStartTime.isAfter(newEndTime) && !newStartTime.isAfter(existingEndTime);
}
}
return false;
}
return false;
});
}
private boolean isDateInRange(LocalDate date, LocalDate rangeStart, LocalDate rangeEnd) {
return !date.isBefore(rangeStart) && !date.isAfter(rangeEnd);
}
private boolean datesOverlap(LocalDate start1, LocalDate end1, LocalDate start2, LocalDate end2) {
return !start1.isAfter(end2) && !start2.isAfter(end1);
}
private boolean isWeekdayType(BattleEvent.BATTLE_REPEAT_TYPE repeatType) {
return repeatType == BattleEvent.BATTLE_REPEAT_TYPE.SUNDAY ||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.MONDAY ||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.TUESDAY ||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.WEDNESDAY ||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.THURSDAY ||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.FRIDAY ||
repeatType == BattleEvent.BATTLE_REPEAT_TYPE.SATURDAY;
}
private DayOfWeek getDayOfWeekFromRepeatType(BattleEvent.BATTLE_REPEAT_TYPE repeatType) {
switch (repeatType) {
case MONDAY: return DayOfWeek.MONDAY;
case TUESDAY: return DayOfWeek.TUESDAY;
case WEDNESDAY: return DayOfWeek.WEDNESDAY;
case THURSDAY: return DayOfWeek.THURSDAY;
case FRIDAY: return DayOfWeek.FRIDAY;
case SATURDAY: return DayOfWeek.SATURDAY;
case SUNDAY: return DayOfWeek.SUNDAY;
default: throw new IllegalArgumentException("Invalid repeat type: " + repeatType);
}
}
private boolean hasOverlappingWeekday(
LocalDate start1, LocalDate end1,
LocalDate start2, LocalDate end2,
DayOfWeek dayOfWeek) {
// 두 범위의 교집합 계산
LocalDate overlapStart = start1.isAfter(start2) ? start1 : start2;
LocalDate overlapEnd = end1.isBefore(end2) ? end1 : end2;
if (overlapStart.isAfter(overlapEnd)) {
return false; // 겹치는 날짜 범위 없음
}
// 겹치는 날짜 범위 내에 해당 요일이 있는지 확인
LocalDate current = overlapStart;
while (!current.isAfter(overlapEnd)) {
if (current.getDayOfWeek() == dayOfWeek) {
return true; // 해당 요일 발견
}
current = current.plusDays(1);
}
return false; // 해당 요일 없음
}
}