본문으로 건너뛰기
홈
기술
기술 전체
프로그래밍68
컴퓨터 과학63
AI48
웹 개발36
인프라33
데이터31
소프트웨어 공학18
소개
← 목록으로프로그래밍 › Java › 기초

Java 달력 만들기

목차

Java 달력 만들기

월간 달력을 출력하려면 두 값이 필요하다. 그 달의 1일이 무슨 요일인지와 마지막 날짜가 며칠인지다. 1일 앞에 빈칸을 채우고 1일부터 마지막 날까지 숫자를 쓰면 된다. 예전 예제는 Calendar와 Scanner를 사용했지만, 날짜 계산은 java.time.YearMonth로 표현하면 월의 길이와 윤년을 직접 계산할 필요가 없다.

flowchart LR
    A[연도·월 입력] --> B[범위 확인]
    B --> C[YearMonth 생성]
    C --> D[1일의 요일로 앞 빈칸 계산]
    C --> E[그 달의 일수 확인]
    D --> F[1일부터 마지막 날까지 출력]
    E --> F
    F --> G[토요일 뒤 줄바꿈]

첫 요일을 칸 번호로 바꾸기

DayOfWeek.getValue()는 월요일이 1, 일요일이 7이다. 이 글의 달력은 일요일부터 시작하므로 getValue() % 7을 사용한다. 그러면 일요일은 0, 월요일은 1, 토요일은 6이 된다. 1일이 목요일이면 숫자 1을 쓰기 전에 빈칸 네 개가 필요하다.

YearMonth.lengthOfMonth()는 해당 연월의 마지막 일자를 돌려준다. 2월이 28일인지 29일인지 직접 분기할 필요가 없다.

전체 코드

import java.time.YearMonth;
import java.util.Scanner;

public class MonthlyCalendar {
    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in)) {
            System.out.print("연도(1~9999): ");
            if (!scanner.hasNextInt()) {
                System.out.println("연도는 숫자로 입력하세요.");
                return;
            }
            int year = scanner.nextInt();

            System.out.print("월(1~12): ");
            if (!scanner.hasNextInt()) {
                System.out.println("월은 숫자로 입력하세요.");
                return;
            }
            int month = scanner.nextInt();

            if (year < 1 || year > 9999 || month < 1 || month > 12) {
                System.out.println("연도 또는 월의 범위를 확인하세요.");
                return;
            }

            printCalendar(YearMonth.of(year, month));
        }
    }

    static void printCalendar(YearMonth target) {
        int offset = target.atDay(1).getDayOfWeek().getValue() % 7;
        int lastDay = target.lengthOfMonth();

        System.out.printf("%d년 %d월%n", target.getYear(), target.getMonthValue());
        System.out.println(" 일 월 화 수 목 금 토");

        for (int i = 0; i < offset; i++) {
            System.out.print("   ");
        }
        for (int day = 1; day <= lastDay; day++) {
            System.out.printf("%3d", day);
            if ((offset + day) % 7 == 0) {
                System.out.println();
            }
        }
        if ((offset + lastDay) % 7 != 0) {
            System.out.println();
        }
    }
}

2024년 2월을 입력하면 1일은 목요일이므로 앞에 빈칸 네 개가 있고, 마지막 날짜는 29일이다.

2024년 2월
 일 월 화 수 목 금 토
              1  2  3
  4  5  6  7  8  9 10
 11 12 13 14 15 16 17
 18 19 20 21 22 23 24
 25 26 27 28 29

기존 코드에서 주의할 점

옛 Calendar 코드에서는 Calendar.MONTH가 0부터 시작해서 입력 월에서 1을 빼야 했다. 또한 첫 주의 빈칸을 출력한 뒤에도 날짜가 7의 배수일 때마다 줄바꿈하면 실제 요일과 줄바꿈 위치가 어긋난다. 위 예제는 첫 요일의 빈칸 수와 날짜를 더한 값으로 한 주가 끝났는지 계산한다.

이 코드는 고정된 너비의 콘솔 문자로 달력을 그린다. 일정 제목이나 다국어 요일명을 넣는 화면이라면 날짜 계산과 UI 렌더링을 분리하는 편이 좋다.

참고: YearMonth API, DayOfWeek API

같은 카테고리의 글