Calendar와 Date 클래스
1. Calendar와 Date
Date는 날짜와 시간을 다룰 목적으로 JDK 1.0부터 제공되어온 클래스이다. 하지만 부족한 점이 많아 JDK 1.1부터
Calendar 라는 새로운 클래스를 내놓았고, 전보다는 나았지만 몇 가지 단점들이 발견되었다.
이를 보완하기 위해 JDK 1.8부터 'java.time'패키지로 새로운 클래스들이 추가 되었다.
자바의 역사가 긴 터라 Calender와 Date는 배우지 않을 수 없었다.
Calendar는 추상 클래스이기 때문에 직접 객체를 생성할 수 없어, 메서드를 통해 인스턴스를 얻어야 한다.
Calendar cal = new Calendar(); // 에러 !! 추상클래스는 인스턴스 생성 불가.
// OK, getInstance() 메서드는 Calendar 클래스를 구현한 클래스의 인스턴스를 반환한다.
Calendar cal = Caleandar.getInstance();
Calendar를 상속받아 완전히 구현한 클래스로는 GregorianCalendar와 BuddhistCalendar가 있는데
getInstance()는 시스템의 국가와 지역설정을 확인해 자동으로 인스턴스를 반환해준다.
2. Date와 Calendar간의 변환
Calendar가 새로 추가되면서 Date는 대부분의 메서드가 'deprecated' 되었으므로 잘 사용되지 않는다.
그렇기 때문에 변환하는 방법을 배워야할 필요가 있다.
1. Calendar를 Date로 변환
Calendar cal = Calendar.getInstance();
...
Date d = new Date(cal.getTimeInMillis()); // Date(long date)
2. Date를 Calendar로 변환
Date d = new Date();
...
Calendar cal = Calendar.getInstance();
cal.setTime(d)
예제1)
getInstance()를 통해서 얻은 인스턴스는 기본적으로 현재 시스템의 날짜와 시간에 대한 정보를 담고 있다.
원하는 날짜나 시간으로 설정하려면 set메서드를 사용하면 된다.
여기서는 'int get(int field)'를 이용해서 원하는 필드의 값을 얻어오는 방법을 보여주기 위한 것이다.
한가지 주의해야할 것은 get(Calendar.MONTH)로 얻어오는 값의 범위가 1~12가 아닌 0~11이라는 것이다.
그래서 get(Calendar.MONTH)로 얻어오는 값이 0이면 1월을 의미하고, 11이면 12월을 의미한다.
예제2)
package Java2;
import java.util.*;
public class CalendarEx2 {
public static void main(String[] args){
// 요일은 1부터 시작하기 때문에, DAY_OF_WEEK[0]은 비워두었다.
final String[] DAY_OF_WEEK = {"","일","월","화","수","목","금","토"};
Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();
// month의 경우 0부터 시작하기 때문에 8월인 경우, 7로 지정해야 한다.
// date.set(2015, Calendar.AUGUST, 15);와 같이 할 수도 있다.
date1.set(2015,7,15);
System.out.println("date1은 " + toString(date1) + DAY_OF_WEEK[date1.get(Calendar.DAY_OF_WEEK)] + "요일이고, ");
System.out.println("오늘(date2)은 " + toString(date2) + DAY_OF_WEEK[date2.get(Calendar.DAY_OF_WEEK)] + "요일입니다.");
// 두 날짜간의 차이를 얻으려면, getTimeInMillis() 천분의 일초 단위로 변환해야한다.
long difference = (date2.getTimeInMillis() - date1.getTimeInMillis()) / 1000;
System.out.println("date1부터 date2까지는 " + difference + "초가 지났습니다.");
System.out.println("일(day)로 계산하면 " + difference/ (24*60*60) + "일입니다."); // 1일 = 24 * 60 *60
}
public static String toString(Calendar date){
return date.get(Calendar.YEAR) + "년 " + (date.get(Calendar.MONTH)+1) + "월 " + date.get(Calendar.DATE) + "일 ";
}
}
결과 :
두 날짜 간의 차이를 구하는 예제이다. 날짜와 시간을 원하는 값으로 변경하려면 set메서드를 사용하면 된다.
void set(int field, int value)
void set(int year, int month ,int date)
void set(int year, int month ,int date, int hourOfDay, int minute)
void set(int year, int month ,int date, int hourOfDay, int minute, int second)
두 날짜 간의 차이를 구하기 위해서는 두 날짜를 최소단위인 초단위로 변경한 다음 그 차이를 구하면 된다.
getTimeInMillis()는 1/1000 초 단위로 값을 반환하기 때문에 초단위로 얻기 위해서는 1000으로 나눠 주어야하고
1단위로 얻기 위해서는 '24(시간)*60(분)*60(초)*1000'으로만 나누어야 한다.
예제에서는 변수 difference에 저장할 때 이미 초단위로 변경하였기 때문에 Day단위로 변경할 때
'24(시간)*60(분)*60(초)'로만 나누었다. 시간상의 전후를 알고 싶을 때는 두 날짜 간의 차이가 양수인지 음수인지를 판단하면 된다.
아니면 간단히 'boolean after(Object when)'와 'boolean before(Object when)'을 사용해도 좋다.
예제3)
package Java2;
import java.util.Calendar;
public class CalendarEx3 {
public static void main(String [] args){
final int [] TIME_UNIT = {3600, 60, 1};
final String[] TIME_UNIT_NAME = {"시간 ", "분 ", "초 "};
Calendar time1 = Calendar.getInstance(); Calendar time2 = Calendar.getInstance();
// time1을 10시 20분 30초로 설정
time1.set(Calendar.HOUR_OF_DAY, 10); time1.set(Calendar.MINUTE, 20); time1.set(Calendar.SECOND, 30);
// time2을 20시 30분 10초로 설정
time2.set(Calendar.HOUR_OF_DAY, 20); time2.set(Calendar.MINUTE, 30); time2.set(Calendar.SECOND, 10);
System.out.println("time1 :" + time1.get(Calendar.HOUR_OF_DAY) + "시 " +
time1.get(Calendar.MINUTE) + "분 " + time1.get(Calendar.SECOND) + "초");
System.out.println("time2 : " + time2.get(Calendar.HOUR_OF_DAY) + "시 " +
time2.get(Calendar.MINUTE) + "분 " + time2.get(Calendar.SECOND) + "초");
long difference = Math.abs(time2.getTimeInMillis() - time1.getTimeInMillis())/1000;
System.out.println("time1과 time2의 차이는 " + difference +"초 입니다.");
String tmp = "";
for(int i = 0 ; i < TIME_UNIT_NAME.length; i++){
tmp += difference / TIME_UNIT[i] + TIME_UNIT_NAME[i];
difference %= TIME_UNIT[i];
}
System.out.println("시분초로 변환하면 " + tmp + "입니다.");
}
}
결과 :
두 개의 시간 데이터로부터 초 단위로 차이를 구한 다음, 시분초로 바꿔 출력하는 예제이다. 가장 큰 단위인 시간 단위(3600초)로 나누고
남은 나머지를 다시 분단위(60초)로 나누면 그 나머지는 초단위 값이 된다.
예제4)
package Java2;
import java.util.Calendar;
public class CalendarEx4 {
public static void main(String[] args){
Calendar date = Calendar.getInstance();
date.set(2015, 7 , 31); // 2015년 8월 31일
System.out.println(toString(date));
System.out.println("= 1일 후 =");
date.add(Calendar.DATE, 1);
System.out.println(toString(date));
System.out.println("= 6달 전 =");
date.add(Calendar.MONTH, -6);
System.out.println(toString(date));
System.out.println("= 31일 후(roll) =");
date.roll(Calendar.DATE,31);
System.out.println(toString(date));
System.out.println("= 31일 후(add) =");
date.add(Calendar.DATE,31);
System.out.println(toString(date));
}
public static String toString(Calendar date){
return date.get(Calendar.YEAR) + "년 " + (date.get(Calendar.MONTH)+1) + "월 " +
date.get(Calendar.DATE) + "일";
}
}
결과 :
'add(int field, int amount)'를 사용하면 지정한 필드의 값을 원하는 만큼 증가 또는 감소 시킬 수 있기 때문에 add메서드를 이용하면
특정 날짜 또는 시간을 기점으로 해서 일정기간 전후의 날짜와 시간도 알아낼 수 있다.
'roll(int field , int amount)'도 지정한 필드의 값을 증가 또는 감소시킬 수 있는데, add메서드와의 차이점은 다른 필드에 영향을 미치지
않는다는 점이다. 예를 들어 add메서드로 날짜필드의 값을 31만큼 증가 시키면 다음 달로 넘어가야 하지만 roll은 그렇지 않다.
단 한가지 예외가 있는데 일 필드(Calendar.DATE)가 말일(end of month)일 때, roll 메서드를 이용해서 월 필드(Month)를 변경하면
일 필드(Date)에 영향을 미칠 수 있다.
예제5)
package Java2;
import java.util.Calendar;
public class CalendarEx5 {
public static void main(String[] args) {
Calendar date = Calendar.getInstance();
date.set(2015, 0 , 31); // 15년 1월 31일
System.out.println(toString(date));
date.roll(Calendar.MONTH,1);
System.out.println(toString(date));
}
public static String toString(Calendar date){
return date.get(Calendar.YEAR) + "년 " + (date.get(Calendar.MONTH)+1) +
"월 " + date.get(Calendar.DATE) + "일";
}
}
결과 :
2015년 1월 31일에 대해 roll()을 호출해서 월 필드를 1 증가 시켰을 때, 월 필드는 2월이 되지만 2월은 31일이 없기 때문에,
2월의 말일인 28일로 자동 변경되었다. add()도 같은 경우에 마찬가지로 변경된다.