[Springboot] 달력에 필요한 직전 달 일정, 다음 달 일정 가져오기

일단 해볼게·2023년 5월 16일
2

Springboot

목록 보기
9/26
post-thumbnail

달력에 필요한 직전 달 일정, 다음 달 일정 가져오려고 한다. 2023년 5월을 예시로 들면, 직전 달 날짜인 4월 30일과 다음 달 날짜인 6월 1, 2, 3일의 일정이 필요하다. 직전 달 날짜를 구하는 기능을 먼저 설명하겠다.

직전 달 일정 가져오기

해당 달 1일의 요일 구하기

  1. LocalDate.of 함수를 이용해서 해당 달 1일을 LocalDate 형식 객체를 만든다.
  2. LocalDate.getDayOfWeek() 함수를 이용해서 DayOfWeek 형식 객체를 만든다.
  3. DayOfWeek.getValue()를 하면 월요일은 1이 반환되고, 일요일은 7이 반환된다.
LocalDate date = LocalDate.of(year, month, 1);
DayOfWeek dayOfWeek = date.getDayOfWeek();
return dayOfWeek.getValue(); // 월요일은 1, 일요일은 7

getValue() 함수 말고 dayOfWeek.getDisplayName()를 이용하면 문자열로 반환받을 수 있다.

해당 달 1일을 기준으로 필요한 요일의 수 찾기

월요일은 1, 일요일은 7을 반환하므로 그대로 이용하면 된다. 다만, 일요일인 경우 필요한 요일이 없으므로 0을 반환하게 한다.

public int getRemainingDay(int numberOfDay) {
        if(numberOfDay == 7) {
            return 0;
        } else {
            return numberOfDay;
        }
    }

해당 월의 첫 날짜 구하기

SQL에서 사용할 Date 객체를 만들기 위해 yearMonth → LocalDate → Date로 형변환했다.

YearMonth yearMonth = YearMonth.of(year, month);
LocalDate firstDayOfMonth = yearMonth.atDay(1);
Date firstDateOfMonth = Date.valueOf(firstDayOfMonth); // 해당 월의 첫번째 날짜

DATE_SUB를 이용해 날짜 차이를 계산해서 일정 가져오기

DATE_SUB를 이용하기 위해 nativeQuery 사용한다.

between을 이용해 날짜 사이의 일정을 구한다.

@Query(nativeQuery = true, value = "select * from task where writer = :memberId " +
            "and is_active = true " +
            "and start_at between DATE_SUB(:firstDateOfMonth, INTERVAL :remainingDay DAY) and :firstDateOfMonth " +
            "order by start_at asc")
    List<Task> findTaskOfBeforeMonth(String memberId, Date firstDateOfMonth, int remainingDay);

다음 달 일정 가져오기

해당 달의 마지막 날짜 구하기

달마다 마지막 날짜가 다르므로 주의하자.

public int getLastDayOfMonth(int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        return yearMonth.lengthOfMonth(); // 해당 월의 마지막 날짜
    }

나머지 과정은 직전 달 일정과 같다.

DATE_ADD를 이용해 날짜 차이를 계산해서 일정 가져오기

DATE_ADD를 이용하기 위해 nativeQuery 사용한다.

between을 이용해 날짜 사이의 일정을 구한다.

@Query(nativeQuery = true, value = "select * from task where writer = :memberId " +
            "and is_active = true " +
            "and start_at between :lastDayOfMonth and DATE_ADD(:lastDayOfMonth, INTERVAL :remainingDay DAY) " +
            "order by start_at asc")
List<Task> findTaskOfAfterMonth(String memberId, Date lastDayOfMonth, int remainingDay);

DATE_ADD, DATE_SUB 주의 사항

  • DATE_ADD, DATE_SUB는 MySQL 기준으로 사용할 수 있는 함수라서 다른 DB를 사용할 때 문법 주의해야한다.
  • MySQL의 DATE_ADD, DATE_SUB 함수는 주어진 날짜의 시, 분, 초 + 더할 날짜이므로 날짜의 시, 분, 초에 따라 일정이 검색되지 않을 수 있으니 주의해야한다.
    • 예를 들어, 현재 시간이 2023년 5월 23일 13시 00분이고 더할 날짜가 3일 이라면 20203년 5월 26일 13시 00분 일정까지만 추출된다.
    • 이걸 해결하기 위해 LocalDate형식을 Date 형식으로 형변환했다. LocalDate는 연, 월, 일까지만 나오므로 시, 분, 초를 고려하지 않아도 된다.

모든 코드 : https://github.com/Techeer-FM-Studio/backend

profile
시도하고 More Do하는 백엔드 개발자입니다.

0개의 댓글