bdfgdfg

Calendar와 Date 그리고 java.time 본문

웹프로그래밍/Java

Calendar와 Date 그리고 java.time

marmelo12 2023. 7. 27. 14:01
반응형

자바의 날짜와 시간과 관련된 클래스는 Date -> Calendar -> java.time에 속한 클래스의 순서로 발전해왔다고 한다.

 

상대적으로 빈약한 Date와 그보다 더 발전한 Calendar. 다만 몇가지의 단점으로 인해 java.time패키지에 속한 클래스들이 기존의 단점을 개선한 버전으로 나왔다곤 하지만.. 이미 Date와 Calendar가 오래 사용되어 왔기에 가볍게 보고는 가야한다.

 

Calendar / GregorianCalendar

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

import java.io.FileInputStream;
import java.util.*;

public class Hello {	
	public static void main(String[] args) 
	{
		Calendar c = Calendar.getInstance();
	}
}

Calendar를 상속받아 완전히 구현한 클래스로는 GregorianCalendar와 BuddhistCalendar가 존재하는데

시스템의 국가와 지역설정을 확인해 태국인 경우 BuddhistCalendar이며 그 외 국가는 GregorianCalendar의 인스턴스를 반환한다고 한다.

 -> 즉 GregorianCalendar와 BuddhistCalendar. 혹은 이후에 생길 Calendar의 자식클래스를 직접 생성하기보단 getInstance를 통해 얻어오는게 좋다.

 

Calendar가 생기면서 Date클래스의 메소드는 대부분 deprecated(권장하지않음)이지만 여전히 사용되는 곳이 있기에 

Calendar <-> Date 서로 변환할일이 생긴다.

import java.io.FileInputStream;
import java.util.*;

public class Hello {	
	public static void main(String[] args) 
	{
		//Calendar를 Date로 변환
		Calendar c = Calendar.getInstance();
		Date d = new Date(c.getTimeInMillis());
		
		//Date를 Calendar로 변환.
		Date d2 = new Date();
		Calendar c2 = Calendar.getInstance();
		c2.setTime(d2);
	}
}

 

캘린더를 통해 오늘 날짜의 시간에 대한 정보를 얻어와보자.

public class Hello {	
	public static void main(String[] args) 
	{
		//Calendar를 Date로 변환
		Calendar c = Calendar.getInstance();
		System.out.println("올해 연도 : " + c.get(Calendar.YEAR));
		System.out.println("월 : (0~11 + 1) : " + ( c.get(Calendar.MONTH) + 1 ) );
		System.out.println("올해 몇째 주 : " + c.get(Calendar.WEEK_OF_YEAR));
		System.out.println("이달 몇째 주 : " + c.get(Calendar.WEEK_OF_MONTH));
		
		System.out.println("이달 몇 일 : " + c.get(Calendar.DATE)); // 혹은 DATE_OF_MONTH
		System.out.println("올해 몇 일 째 : " + c.get(Calendar.DAY_OF_YEAR));
		System.out.println("무슨요일?(1:일요일~) : " + c.get(Calendar.DAY_OF_WEEK));
		System.out.println("이달 몇 째 요일 : " + c.get(Calendar.DAY_OF_WEEK_IN_MONTH));
		System.out.println("오전 오후?(오전 : 0, 오후 : 1) : " + c.get(Calendar.AM_PM));
		System.out.println("몇시?(0~11) : " + ( c.get(Calendar.HOUR)));
		System.out.println("몇시?(0~23) : " + ( c.get(Calendar.HOUR_OF_DAY)));
		System.out.println("분?(0~59) : " + ( c.get(Calendar.MINUTE)));
		System.out.println("분?(0~59) : " + ( c.get(Calendar.SECOND)));
		
	}
}

위와 같은 내부 static 멤버변수를 통해 현재 날짜와 시간에 대한 값을 가져올 수 있다.

참고로 월은 0~11이므로 +1해주어야함.

 

Calendar의 다양한 예제는 많기도하고 내부 메소드도 다양해서 필요할 때 찾아쓰면 될듯.

 

java.time 패키지

java.time 패키지에 속한 클래스들의 가장 큰 특징은 String 클래스처럼 불변. 

날짜나 시간을 변경하는 메소드들은 기존의 객체를 수정하는게 아닌 매번 생성해서 반환한다고 한다.

 -> 기존 Calendar클래스는 변경이 가능하기에 Thread-Safe하지 않음.

 

java.time패키지에는 시간을 표현할 때 LocalTime, 날짜를 표현할 땐 LocalDate클래스를 사용한다.

그리고 둘 다 필요하다면 LocalDateTime클래스를 이용하면 된다.

여기서 시간대까지 다루어야한다면 ZonedDAteTime클래스를 이용.

 

참고로 Instant클래스도 있는데 이 클래스는 날짜와 시간을 초단위(나노초)로 표현하고 날짜와 시간을 정수로 표현할 수 있으므로 날짜와 시간의 차이를 계산하거나 순서를 비교하는데 유리해서 DB에 많이 사용된다고 한다.

 

Period와 Duraion 클래스도 존재한다.

날짜 - 날짜= Period

시간 - 시간 = Duration

즉 각각 두 날짜, 시간의 차이를 표현하기 위한 것.

 

이제 실제로 LocalTime,LocalDate를 사용해보자

public class Hello {	
	public static void main(String[] args) 
	{
		LocalDate dt = LocalDate.now();
		System.out.println("Year : " + dt.getYear());
		System.out.println("Month : " + dt.getMonth());
		System.out.println("Day : " + dt.getDayOfWeek());
		
		LocalTime t = LocalTime.now();
		System.out.println("Hour : " + t.getHour());
		System.out.println("Minute : " + t.getMinute());
		System.out.println("Sec : " + t.getSecond());
	}
}

Year : 2023

Month : JULY

Day : THURSDAY

Hour : 13

Minute : 59

Sec : 41

사용방법은 비슷비슷하다. now메소드를 통해서 현재 날짜와 시간값을 얻어올 수 있고.

그게 아니라면 of메소드를 통해서 날짜와 시간값을 직접 지정해줄 수 있다.

getmonth와 getDayOfWeek은 열거형을 반환하는데, 한번더 getValue메소드를 통해서 정수형 값을 얻어올수도 있다.

 -> 주의점은 Calendar와 달리 월은 1~12이고 일요일은 7이다. 1 : 월요일 ~ 7: 일요일

 

이 외에 with,plus,minus,truncatedTo 메소드도 존재한다.

with() : 날짜와 시간을 특정 값으로 변경

plus,minus는 이름그대로 해당 날짜와 시간값을 주어진 값을 통해 덧셈,뺄셈 연산을 한다.

truncatedTo메소드는 지정된 것보다 작은 단위의 필드를 0으로 만든다.

 -> 즉 truncatedTo(ChronoUnit.HOURS)를 넘기면 Hour보다 작은 필드인 minute을 0으로 만든다.

 

날짜와 시간의 비교 isAfter,isBefore,isEqual

isAfter() : 이후 날짜인지 검사

- A.isAfter(B) : A가 B 이후이면 true 이다.

isBefore() : 이전 날짜인지 검사

- A.isBefore(B) : A가 B 이전이면 true 이다.

isEqual() : 날짜가 동일한지 검사

- A.isEqual(B) : A가 B와 같은 날짜라면 true. 

 -> 그냥 equal함수도 있는데 이건 연표(chrnology)가 다르면 날짜가 같더라도 false를 반환한다.

 

Instant

Instant는 에포크타임(EPOCH TIME, 1970-01-01 00:00:00 UTC)부터 경과된 시간을 나노초 단위로 표현한다.(utc기준)

사람이 읽기엔 불편하지만 계산이 쉽다는 장점이 있다.

import java.io.FileInputStream;
import java.util.*;
import java.time.*;
import java.time.temporal.ChronoUnit;

public class Hello {	
	public static void main(String[] args) 
	{
		Instant s = Instant.now();
		
		long epochSec = s.getEpochSecond(); // 에포치로부터 초단위 값을 가져온다.
		int nano = s.getNano(); // 에포치로부터 나노초단위 값을 가져온다.
		
		System.out.println(epochSec);
		System.out.println(nano);
	}
}

오라클 DB에서 밀리초 단위의 EPOCHTIME을 위해 toEpochMilli메소드도 존재한다.

 

TemporalAdjusters

현재 시간대에서 지난주 토요일이 며칠인지, 혹은 이번달의 3번째 금요일은 며칠인지와 같은 날짜계산은 앞선 plus, minus로는 불편하다.

 

그래서 자주 쓰일만한 날짜 계산을 모아둔것이 TemporalAdjusters클래스.

import java.io.FileInputStream;
import java.util.*;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;

public class Hello {	
	public static void main(String[] args) 
	{
		LocalDate dt = LocalDate.now(); // 2023-07-27
		LocalDate prevFriday = dt.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY)); // 2023-07-21
		
		int a = 0;
	}
}

 

Period와 Duration

앞서 Period는 날짜의차이, Duration은 시간의차이.

import java.io.FileInputStream;
import java.util.*;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;

public class Hello {	
	public static void main(String[] args) 
	{
		LocalDate dt = LocalDate.of(2015, 8, 20);
		LocalDate dt2 = LocalDate.of(2018, 10, 20);
		
		Period pe = Period.between(dt, dt2);
		System.out.println("Period Year : " + pe.getYears());
		System.out.println("Period Months : " + pe.getMonths());
		System.out.println("Period Days : " + pe.getDays());

		LocalTime t = LocalTime.of(8, 14, 20);
		LocalTime t2 = LocalTime.of(10, 14, 20);
		
		Duration du = Duration.between(t, t2);
		// Duration은 getHour,getMinute이 없기에 밑과같이 변환하여 구한다.
		LocalTime tmpDurationTime = LocalTime.of(0, 0).plusSeconds(du.getSeconds());
		System.out.println("Duration Hour : " + tmpDurationTime.getHour() );
		System.out.println("Duration Minute : " + tmpDurationTime.getMinute() );
		System.out.println("Duration Seconds : " + tmpDurationTime.getSecond() );
	}
}

Period Year : 3

Period Months : 2

Period Days : 0

Duration Hour : 2

Duration Minute : 0

Duration Seconds : 0

 

 

관련된 내용이 많기도하고 다 외울수는 없기에 필요할때마다 검색해서 갖다쓰는게 좋겠다.

반응형
Comments