로직과의 사투/Java

월요일 기준으로 주차 구하기 java.time

무조건 월요일 기준으로 주차 구하기.

  현재 진행중인 프로젝트에서 date와 관련된 데이터를 다루는 일이 많다. 웬만하면 Java8 Time API의 기본적인 Methods 로 해결 가능한 경우가 많지만, 계산이 필요한 경우도 더러 있다.

특히 가장 골머리를 썩이게 만든 부분은 몇 주차 계산 이었다. Java8의 Time API에서도 ChronoField의 ALIGNED_WEEK_OF_MONTH를 이용해 손 쉽게 몇 주차인지 알 수 있지만 현재 프로젝트의 요구사항과 맞지 않는 값이었다.

 

  왜 그러한가 찾아보았더니 생각보다 쉽지 않다는걸 깨달았다.

 

  주차를 나누는 국제 표준인 ISO 8601 에서 정하길, 주차를 나누는 기준은 그 주의 시작이 목요일 이후냐 아니냐 (한국 국가기술표준원에선 이를 '어떤 월의 날짜가 그 주간의 과반수 이상을 차지하고 있는가' 로 표현했다.) 로 나뉘는 기준이었고 진행중인 프로젝트에서 원하는 값은 무조건 월요일로 그 주를 시작한다는 것이었다. 예컨대, 2020년 12월 1일은 화요일이지만 월요일이 아니기 때문에 12월 1주차가 아닌 11월 5주차가 되는 것. 이렇게 되면 11월 5주차의 11월은 단 하루지만 요구사항을 맞춰야 하기 때문에 억지로 월요일 기준으로 주차를 나누는 메소드를 작성하였다.

 

    public Integer getWeekNumber (LocalDate date) {
        LocalDate firstMondayOfMonth = date.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));

        // 첫 월요일이면 바로 리턴
        if (firstMondayOfMonth.isEqual(date)) return 1;

        if (date.isAfter(firstMondayOfMonth)) {
            // 첫 월요일 이후일 때
            int diffFromFirstMonday = date.getDayOfMonth() - firstMondayOfMonth.getDayOfMonth();
            int weekNumber = (int) Math.ceil(diffFromFirstMonday / 7.0);
            if (date.getDayOfWeek() == DayOfWeek.MONDAY) weekNumber += 1;
            return weekNumber;
        }
        // 첫 월요일 이전이면 회귀식으로 전 달 마지막 주차를 구함
        return getWeekNumber(date.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth()));
    }

  다행히 이 주차 데이터는 단순 Integer를 return 하거나 String 타입으로 이용해도 상관없어 생각보다 간단하게 작성할 수 있었다.

 해당 월의 첫 월요일을 구한 뒤 그 월요일과 해당 날짜의 차를 이용해 구하는 방식을 생각해보았다. 만약 첫 월요일 이전 날짜라면 직전 월의 마지막 날을 회귀식으로 넘겨 구할 수 있게 짰다.

 

  아직 많은 테스트를 거치지 않아 문제점은 나중에 발견될 수 있겠지만 지금은 여기서 만족해야할 것 같다.