본문 바로가기
Back-end

10 날짜와 시간 & 형식화(1)

by 신재권 2021. 7. 2.

Calendar와 Date

Date는 날짜와 시간을 다룰 목적으로 JDK1.0부터 제공되어온 클래스이다. JDK1.0이 제공하는 클래스의 수와 기능은 지금과 비교할 수 없을 정도로 빈약했다. Date클래스 역시 기능이 부족했기 때문에 , 서둘러 Calendar라는 새로운 클래스를 그 다음 버전인 JDK1.1부터 제공하기 시작했다. Calendar는 Date보다는 훨씬 나았지만 몇 가지 단점들이 발견되었다. 늦은 감이 있지만 JDK1.8부터 'java.time패키지'로 기존의 단점들을 개선한 새로운 클래스들이 추가되었다.

새로 추가된 java.time패키지만 배우면 좋을 텐데, 아쉽게도 Calendar와 Date는 자바의 탄생부터 지금까지 20년이 넘게 사용되어 왔고, 지금도 계속 사용되고 있으므로 배우지 않고 넘어갈 수가 없다. 그렇다고 해서 Calendar와 Date의 기능을 깊게 배울필요는 없다.

  • 여기서 말하는 Date클래스는 java.util패캐지에 속한 것이다. java.sql패키지의 Date클래스와 혼동하지 말자.

Calendar와 GregorianCalendar

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

Calendar cal = new Calendar(); //에러, 추상클래스는 인스턴스를 생성할 수 없다.
//OK, getInstance()메서드는 Calendar클래스를 구현한 클래스의 인스턴스를 반환한다.
Calendar cal  = Calendar.getInstance();

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

GregorianCalendar는 Calendar를 상속받아 오늘날 전세계 공통으로 사용하고 있는 그레고리력에 맞게 구현한 것으로 태국을 제외한 나머지 국가에서는 GregorianCalendar를 사용하면 된다.

인스턴스를 직접 생성해서 사용하지 않고 이처럼 메서드를 통해서 인스턴스를 반환받게 하는 이유는 최소한의 변경으로 프로그램이 동작할 수 있게 하기 위한것이다.

class MyApplication{
	public static void main(String[] args){
		Calendar cal  =new GregorianCalendar();  //경우에 따라 이 부분을 변경해야 한다.
	...	
	}
}

만일 위와 같이 특정 인스턴스를 생성하도록 프로그램이 작성되어 있다면, 다른 종류의 역법(calendar)을 사용하는 국가에서 실행한다던가, 새로운 역법이 추가된다던가 하는 경우, 즉 다른 종류의 인스턴스를 필요로 하는 경우에 MyApplication을 변경해야 하는데 비해 아래와 같이 메서드를 통해서 인스턴스를 얻어오도록 하면 MyApplication을 변경하지 않아도 된다.

대신 getInstance()의 내용은 달라져야 하겠지만, MyApplication이 변경되지 않아도 된다는 것이 중요하다. getInstance()메서드가 static인 이유는 메서드 내의 코드에서 인스턴스 변수를 사용하거나 인스턴스 메서드를 호출하지 않기 떄문이며, 또 다른 이유는 getInstance()가 static이 아니라면 위와 같이 객체를 생성한 다음에 호출해야 하는데 Calendar는 추상클래스이기 때문에 객체를 생성할 수 없기 때문이다.

Date와 Calendar간의 변환

Calendar가 새로 추가되면서 Date는 대부분의 메서드가 deprecated되었으므로 잘 사용되지 않는다. 그럼에도 불구하고 여전히 Date를 필요로 하는 메서드들이 있기 때문에 Calendar를 Date로 또는 그 반대로 변환할 일이 생긴다. 그럴 때는 다음과 같이 하자.

  • Java API문서를 보면 더 이상 사용을 권장하지 않는 대상에 deprecated가 붙어있다.
1. Calendar를 Date로 변환
Calendar cal = Calendar.getInstace();
	...
Date d = new Date(cal.getTimeInMillis());  //Data(long date)

2. Date를 Calendar로 변환
Date d = new Date();
	...
Calendar cal = Calendar.getInstace();
cal.setTime(d)
import java.util.Calendar;


public class CalendarEx1 {

	public static void main(String[] args) {
		//기본적으로 현재 날짜와 시간으로 설정된다.
		Calendar today = Calendar.getInstance();
		System.out.println("이 해의 년도 : "+today.get(Calendar.YEAR));
		System.out.println("월(0~11, 0:1월) : "+today.get(Calendar.MONTH));
		System.out.println("이 해의 몇 째 주 : "+today.get(Calendar.WEEK_OF_YEAR));
		System.out.println("이 달의 몇 쨰 주 : "+today.get(Calendar.WEEK_OF_MONTH));
		
		//DATE와 DAY_OF_MONTH는 같다
		System.out.println("이 달의 몇 일 :"+today.get(Calendar.DATE));
		System.out.println("이 달의 몇 일 :"+today.get(Calendar.DAY_OF_MONTH));
		System.out.println("이 달의 몇 일 :"+today.get(Calendar.DAY_OF_YEAR));
		System.out.println("요일(1~7, 1: 일요일) : "+today.get(Calendar.DAY_OF_WEEK)); //1 :일요일 2: 월요일
		System.out.println("이 달의 몇 쨰 요일 :"+today.get(Calendar.DAY_OF_WEEK_IN_MONTH));
		
		System.out.println("오전_오후(0:오전, 1: 오후):"+today.get(Calendar.AM_PM));
		System.out.println("시간(0~11):"+today.get(Calendar.HOUR));
		System.out.println("시간(0~23):"+today.get(Calendar.HOUR_OF_DAY));
		System.out.println("분(0~59):"+today.get(Calendar.MINUTE));
		System.out.println("초(0~59):"+today.get(Calendar.SECOND));
		System.out.println("1000분의 1초(0~999): "+today.get(Calendar.MILLISECOND));
		
		//천분의 1초를 시간으로 표시하기 위해 3600000으로 나누었다. (1시간 = 60 * 60초)
		System.out.println("TimeZone(-12~+12) : "+(today.get(Calendar.ZONE_OFFSET)/(60*60*1000))); 
		System.out.println("이 달의 마지막 날 : "+today.getActualMaximum(Calendar.DATE)); //이 달의 마지막 일을 찾는다.

	}

}
---------------------------
이 해의 년도 : 2021
월(0~11, 0:1월) : 6
이 해의 몇 째 주 : 27
이 달의 몇 쨰 주 : 1
이 달의 몇 일 :2
이 달의 몇 일 :2
이 달의 몇 일 :183
요일(1~7, 1: 일요일) : 6
이 달의 몇 쨰 요일 :1
오전_오후(0:오전, 1: 오후):0
시간(0~11):0
시간(0~23):0
분(0~59):43
초(0~59):14
1000분의 1초(0~999): 483
TimeZone(-12~+12) : 9
이 달의 마지막 날 : 31

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

여기서는 int get(int field)를 이용해서 원하는 필드의 값을 얻어오는 방법을 보여주기 위한 것이다.

public final static int YEAR = 1;

get메서드의 매개변수로 사용되는 int값들은 Calendar에 정의된 static상수이다. 이 예제에서는 자주 쓰이는 것들만 골라놓은 것인데 실제로는 더 많은 필드들이 정의되어 있으니 보다 자세한 내용은 Java API문서를 참고하자.

System.out.println("월(0~11, 0:1월): "+today.get(Calendar.MONTH));

한 가지 주의해야 할 것은 get(Calendar.MONTH)로 얻어오는 값의 범위가 1~12가 아닌 0~11이라는 것이다. 그래서 get(Calendar.MONTH)로 얻어오는 값이 0이면 1월을 의미하고, 11이면 12월을 의미한다.