주말﹒공휴일 계산기

xellos·2022년 8월 13일
0

Java

목록 보기
1/1

의존성 추가

<!--양력, 음력 변환 라이브러리-->
<dependency>
  <groupId>com.ibm.icu</groupId>
  <artifactId>icu4j</artifactId>
  <version>71.1</version>
</dependency>

코드 작성

1) CalendarType

public enum CalendarType {
	SUN, MOON
}

2) Holiday

@Getter
public enum Holiday {
    NEW_YEAR_DAY(CalendarType.SUN, 1, 1, false),             //신정
    THREE_ONE_DAY(CalendarType.SUN, 3, 1, true),             //삼일절 - 대체 공휴일: 토요일, 일요일
    CHILDREN_DAY(CalendarType.SUN, 5, 5, true),              //어린이날 - 대체 공휴일: 토요일, 일요일
    MEMORIAL_DAY(CalendarType.SUN, 6, 6, false),             //현충일
    NATIONAL_LIBERATION_DAY(CalendarType.SUN, 8, 15, true),  //광복절 - 대체 공휴일: 토요일, 일요일
    NATIONAL_FOUNDATION_DAY(CalendarType.SUN, 10, 3, true),  //개천절 - 대체 공휴일: 토요일, 일요일
    HANGUL_DAY(CalendarType.SUN, 10, 9, true),               //한글날 - 대체 공휴일: 토요일, 일요일
    CHRISTMAS_DAY(CalendarType.SUN, 12, 25, false),          //크리스마스
    MOON_NEW_YEAR_DAY(CalendarType.MOON, 1, 1, true),        //설날 - 대체 공휴일: 일요일
    BUDDHA_COMING_DAY(CalendarType.MOON, 4, 8, false),       //부처님 오신날
    THANKSGIVING_DAY(CalendarType.MOON, 8, 15, true);        //추석 - 대체 공휴일: 일요일
    
    private CalendarType calendarType;
    private int month;
    private int day;
    private boolean subHoliday; //대체 휴일 여부
    
    Holiday(CalendarType calendarType, int month, int day, boolean subHoliday) {
      this.calendarType = calendarType;
      this.month = month;
      this.day = day;
      this.subHoliday = subHoliday;
    }
    
    public boolean isSunTypeCalendar() {
      return this.calendarType == CalendarType.SUN;
    }
}

3) HolidayChecker

public class HolidayChecker {
  private List<LocalDate> getHolidayList() {
    List<LocalDate> holidayList = new ArrayList<>();
    int year = LocalDate.now().getYear();
    
    Holiday[] holidays = Holiday.values();
    for(Holiday holiday : holidays) {
      if(holiday.isSunTypeCalendar()) { //양력인 공휴일
        LocalDate localDate = LocalDate.of(year, holiday.getMonth(), holiday.getDay());
        
        //공휴일을 추가
        holidayList.add(localDate);
        
        //대체 공휴일이 적용되는 경우
        LocalDate subHoliday = calculateSubHoliday(holiday, localDate);
        if(subHoliday != null) holidayList.add(subHoliday);
        
      } else { //음력인 공휴일
        //석가탄신일인 경우
        if(holiday == Holiday.BUDDHA_COMING_DAY) {
          LocalDate mainHoliday = transferToSunCalendarTypeDate(year, holiday);
          holidayList.add(mainHoliday);
          contiunue;
        }
        
        //설과 추석인 경우
        LocalDate mainHoliday = transferToSunCalendarTypeDate(year, holiday);
        LocalDate plusOneMainHoliday = mainHoliday.plusDays(1);
        LocalDate minusOneMainHoliday = mainHoliday.minusDays(1);
        
        //공휴일을 추가
        holidayList.add(mainHoliday);
        holidayList.add(plusOneMainHoliday);
        holidayList.add(minusOneMainHoliday);
        
        //대체 공휴일 계산
        LocalDate subHoliday = calcSubHoliday(mainHoliday, pluOneMainHoliday, minusOneMainHoliday);
        if(subHoliday != null) holidayList.add(subHoliday);
      }
    }
    
    return holidayList.stream().sorted().collect(Collectors.toList());
  }
  
  private LocalDate calculateSubHoliday(Holiday holiday, LocalDate localDate) {
    DayOfWeek dayOfWeek = localDate.getDayOfWeek();
    int value = dayOfWeek.getValue(); //1: Monday ~ 7: Sunday
    
    if(holiday.isSubHoliday()) {
      //토요일인 경우 +2일을 더해서 다음주 월요일을 대체 휴일로 만든다.
      if(value == 6) return localDate.plusDays(2);
      
      //일요일인 경우 +1일을 더해서 다음주 월요일을 대체 휴일로 만든다.
      if(value == 7) return localDate.plusDays(1);
    }
    
    return null;
  }
  
  //음력인 날짜를 양력으로 변환한다.
  private LocalDate transferToSunCalendarTypeDate(int year, Holiday holiday) {
    ChineseCalendar cc = new ChineseCalendar();
    Calendar cal = Calcendar.getInstance();
    cc.set(ChineseCalendar.EXTENDED_YEAR, year + 2637);
    cc.set(ChineseCalendar.MONTH, holiday.getMonth() - 1);
    cc.set(ChineseCalendar.DAY_OF_MONTH, holiday.getDay());
    
    cal.setTimeInMillis(cc.getTimeInMillis());
    
    return LocalDate.ofInstant(cal.toInstant(), ZoneId.systemDefault());
  }
  
  private LocalDate calcSubHoliday(LocalDate mainHoliday, LocalDate plusOneMainHoliday, LocalDate minusOneMainHoliday) {
    if(minusOneMainHoliday.getDayOfWeek().getValue() == 7)
      return minusOneMainHoliday.plusDays(3);
    
    if(mainHoliday.getDayOfWeek().getValue == 7)
      return mainHoliday.plusDays(2);
      
    if(plusOneMainHoliday.getDayOfWeek().getValue() == 7)
      return plusOneMainHoliday.plusDays(1);
      
    return null;
  }
}

사용

public boolean isPassDay() {
  //주말 여부: 주말이면 로직을 실행하지 않는다.
  LocalDate now = LocalDate.now();
  int value = now.getDayOfWeek().getValue();
  if(value == 6) return true;
  if(value == 7) return true;
  
  //공휴일 + 대체 공휴일 여부: 해당하면 로직을 실행하지 않는다.
  HolidayChecker holidayChecker = new HolidayChecker();
  List<LocalDate> holidayList = holidayChecker.getHolidayList();
  return holidayList.contains(now);
}

0개의 댓글