[기본 개념] 5 | (1.1) Calendar, Date

728x90

[기본 개념] 5 | (1.1) Calendar, Date

1> Calendar와 Date

1. Calendar와 Date

Calendar와 GregorianCalendar

 Calendar는 추상클래스이기 때문에 직접 객체생성 대신 메서드를 통해 완전히 구현된 클래스의 인스턴스를 얻어야 한다.

 

// getInstance( )메서드는 Calendar클래스를 구현한 클래스의 인스턴스 반환

Calendar cal = Calendar.getInstance( ) ;   

 

 Calendar를 상속받아 구현한 시스템의 국가와 지역 설정을 확인하는 BuddhistCalendar, GregorianCalendar가 있는데, BuddhistCalendar의 getInstance( )는 태국인 경우 BuddhistCalendar의 인스턴스를 반환하고, 그 외에는 GregorianCalendar의 인스턴스를 반환한다.

 

Date와 Calendar간의 변화

Calendar를 Data로 또는 그 반대로 변환할 일이 있다.

 

1 Calendar를 Data로 변환

    

    Calendar cal = Calendar.getInstance( ) ;

     . . .

    Data d = new Data(cal.getTimeInMillis( )) ;     // Data(long data)

 

2 Data를 Calendar로 변환

 

    Data d = new Data( ) ;

     . . .

    Calendar cal = Calendar.getInstance( ) ;

    cal.setTime(d) ;

 

 getInstance( )를 통해서 얻은 인스턴스는 기본적으로 현재 시스템의 날짜와 시간에 대한 정보를 담고 있다. 원하는 날짜나 시간으로 설정하려면 set메서드를 사용하면 된다.

 

 

이 해의 년도 today.get(Calendar.YEAR) ; 2021
월(0 ~ 11) today.get(Calendar.MONTH) ; 10    <-- 11월
이 해의 몇 째 주 today.get(Calendar.WEEK_OF_YEAR) ; 49
이 달의 몇 째 주 today.get(Calendar.WEEK_OF_MONTH) ; 4
이 달의 며칠 today.get(Calendar.DATE) ; (DATE와 DAY_OF_MONTH는 같다.) 30
이 달의 며칠 today.get(Calendar.DAY_OF_MONTH) ; 30
이 해의 며칠 today.get(Calendar.DAY_OF_YEAR) ; 334
요일(1 ~7) today.get(Calendar.DAY_OF_WEEK) ; 3
이 달의 몇 째 요일 today.get(Calendar.DAY_OF_WEEK_IN_MONTH) ; 4
오전_오후(0 : 오전, 1 : 오후) today.get(Calendar.AM_PM) ; 1
시간(0 ~ 11) today.get(Calendar.HOUR) ; 7
시간(0 ~ 23) today.get(Calendar.HOUR_OF_DAY) ; 19
분(0 ~ 59) today.get(Calendar.MINUTE) ; 45
초(0 ~ 59) today.get(Calendar.SECOND) ; 12
1000분의 1초(0 ~ 999) today.get(Calendar.MILLISECOND) ; 559
TimeZone(-12 ~ +12) today.get(Calendar.ZONE_OFFSET) / (60 * 60 * 1000)) ; 9
이 달의 마지막 날 today.getActualMaximum(Calendar.DATE) ; 30

 

 이때, get(Calendar.MONTH)로 얻어오는 값은 범위가 0 ~ 11이므로 0이면 1월이고, 11이면 12월을 의미한다.

 

 두 날짜 간의 차이는 초단위로 변경한 다음 차이를 구하면 된다. 시간상의 전후를 알고 싶을 때는 간단히 'boolean after(Object when)'와 'boolean before(Object when)'을 사용해도 된다.

 

 'add(int field, int amount)'를 사용하면 지정한 필드의 값을 원하는 만큼 증가 또는 감소시킬 수 있다. 'roll(int field, int amount)'도 지정한 필드의 값을 증가 또는 감소시킬 수 있는데 차이점은 다른 필드에 영향을 미치지 않는다는 것이다.

 

 예를 들어 add메서드로 날짜 필드(Calendar.DATE)의 값을 31만큼 증가시켰다면 다음 달로 넘어가므로 월 필드(Calendar.MONTH) 값도 증가하지만, roll메서드는 날짜 필드의 값만 바뀐다. 단, 일필 드가 말일일 때, roll메서드를 이용해서 월 필드를 변경하면 일 필드에 영향을 미칠 수도 있다.

 

예제/CalendarEx7.java

import java.util.*;

public class CalendarEx7 {
    public static void main(String[] args) {
        if (args.length != 2) {
            System.out.println("Usage : java CalendarEx7 2021 11");
            return;
        }

        int year = Integer.parseInt(args[0]);
        int month = Integer.parseInt(args[1]);

        Calendar sDay = Calendar.getInstance();     // 시작일
        Calendar eDay = Calendar.getInstance();     // 끝일

        // 월의 경우 0부터 11까지의 값을 가지므로 1을 빼야 한다.
        // 입력월의 1일로 설정
        sDay.set(year, month - 1, 1);
        // 입력월의 말일로 설정
        eDay.set(year, month - 1, sDay.getActualMaximum(Calendar.DATE));
        // 1일이 속한 주의 일요일로 날짜설정
        sDay.add(Calendar.DATE, -sDay.get(Calendar.DAY_OF_WEEK) + 1);
        // 말일이 속한 주의 토요일로 날짜설정
        eDay.add(Calendar.DATE, - eDay.get(Calendar.DAY_OF_WEEK) + 7);

        System.out.println("          " + year + "년 " + month + "월");
        System.out.println("  SU  MO  TU  WE  TH  FR  SA");

        // 시작일부터 마지막일까지 1일씩 증가시키면서 출력
        for (int n = 1; sDay.before(eDay) || sDay.equals(eDay); sDay.add(Calendar.DATE, 1)) {
            int day = sDay.get(Calendar.DATE);
            System.out.print((day < 10) ? "   " + day : "  " + day);
            // 7일치를 찍고 줄을 바꾼다.2
            if (n++ % 7 == 0)
                System.out.println();
        }
    }
}
실행결과

          2021년 11월
  SU  MO  TU  WE  TH  FR  SA
  31   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  30   1   2   3   4

 

 커맨드라인으로 년과 월을 입력하면 달력을 출력하는 예제이다. 다음 달의 1일에서 하루를 빼면 이번 달의 마지막 일을 알 수 있다.

 

날짜 계산을 위한 몇 가지 메서드이다.

 

boolean isLeapYear(int year)

    : 매개변수 year가 윤년이면 true, 그렇지 않으면 false를 반환

int dayDiff(int y1, int m1, int d1, int y2, int m2, int d2)

    : 두 날짜 간의 차이를 일단위로 변환

int getDayOfWeek(int year, int month, int day)

    : 지정한 날짜의 요일을 반환(1 ~ 7)

String convertDayToDate(int day)

    : 일단위의 값을 년월일의 형태의 문자열로 변환하여 반환

int convertDateToDay(int year, int month, int day)

    : 년월일을 입력받아서 일단위로 변환

 

 

 

 

출처 | Java의 정석 (남궁 성)

728x90