[자바]/자바의 정석 - 3판

Chapter 10 날짜와 시간 & 형식화

쿠릉쿠릉 쾅쾅 2021. 11. 8. 15:00
728x90

 

 

날짜와 시간 관련 클래스 및 패키지

 

① java.util.Date

  • 날짜와 시간을 다룰 목적으로 만들어진 클래스
  • Date 클래스의 메서드는 거의 deprecated 되어있음
    • Java API 문서에 더 이상 사용을 권장하지 않는 대상에 deprecated가 붙어있음
  • 항상 날짜와 시간을 같이 다룸 (단점)
  • 안쓰는 것을 추천
  • java.util.Date클래스와 java.sql.Date 클래스는 서로 다른 클래스

 

② java.util.Calendar

  • Date 클래스를 개선한 새로운 클래스
  • 항상 날짜와 시간을 같이 다룸 (단점)
  • 덜 쓰는 것을 추천

 

③ java.time 패키지

  • Date와 Calendar의 단점을 개선한 새로운 클래스
  • time 패키지 쓸 것을 추천
  • 날짜와 시간을 따로 다룰 수 있음 (장점)
    • 날짜 : LocalDate
    • 시간 : LocalTime
    • 날짜와 시간 같이 다룸 : LocalDateTime

 

 

 

 

 

▒ 날짜와 시간

 

◎ Calendar 클래스

  • 추상 클래스이므로 직접 인스턴스 생성 못함
    •  Calendar cal = new Calendar();    → 에러!!
  • getInstance() 메서드를 통해서 완전히 구현된 클래스의 인스턴스를 얻어야함
    • Calendar cal = Calendar.getInstance();  → OK.
  • import java.util.Calendar; 쓸 것
  • Calendar 클래스는 불변이 아닌 변경이 가능하므로 멀티 쓰레드 환경에서 안전하지 못함

 

 

□ Calendar 클래스 생성

Calendar cal = Calendar.getInstance();  // ok.

// Calendar cal = new Calendar();  // 에러. 추상클래스이므로 직접 인스턴스 생성 못함

 

 

■  Date와 Calendar 변환

  • Date 클래스의 메서드는 잘 안쓰이지만 Date 클래스를 필요로 하는 메서드가 있음

□ Calendar → Date 변환

Calendar cal = Calendar.getInstance();

Date d = new Date(cal.getTimeInMillis());

 

 

□ Date → Calendar 변환

Date d = new Date();

Calendar cal = Calendar.getInstance();

cal.setTime(d);

 

■ Calender 클래스의 상수

필드명 설명
static int YEAR
static int MONTH 월 (0부터 시작)  ex) 0월 → 실질적으로 1 월 의미
static int WEEK_OF_YEAR 그 해의 몇 번 째 주 ( 1월1일부터 ~ 지금까지 몇번 째 주인지) 
static int WEEK_OF_MONTH 그 달의 몇 번째 주
static int DATE 일  (= DAY_OF_MONTH 와 기능 동일)
static int DAY_OF_MONTH 그 달의 몇 번째 일 (= DATE와 기능 동일 )
static int DAY_OF_YEAR 그 해의 몇 번재 일 (1월1일부터 며칠 지났는지)
static int DAY_OF_WEEK 요일 (범위 : 1~7),  1 : 일요일. 2 : 월요일, 3 : 화요일 .....
static int DAY_OF_WEEK_IN_MONTH 그 달의 몇 번째 요일
static int HOUR 시간 (0~11)
static int HOUR_OF_DAY 시간(0~23)
static int MINUTE
static int SECOND
static int MILLISECOND 천분의 일초 (1/1000 초)  (범위 : 0~999)
static int ZONE_OFFSET GMT 기준 시차 (천분의 일초 단위)
시간 단위로 값을 얻고 싶으면 (60*60*1000)을 나눠야함
시간 단위로 값을 얻을 때 나올 수 있는 값 범위 : -12 ~ 12
한국은 9시간 차이가 나므로 시간 단위로 값을 구하면 9 반환
static int AM_PM 오전/오후 구별. (0 : 오전, 1: 오후)
static int AM 오전
static int PM 오후

 

필드명 설명
static int JANUARY 0 (1월)
static int FEBRUARY 1 (2월)
static int MARCH 2 (3월)
static int APRIL 3 (4월)
static int MAY 4 (5월)
static int JUNE 5 (6월)
static int JULY 6 (7월)
static int AUGUST 7 (8월)
static int SEPTEMBER 8 (9월)
static int OCTOBER 9 (10월)
static int NOVEMBER 10 (11월)
static int DECEMBER 11 (12월)

 

필드명 설명
static int SUNDAY 1 (일요일)
static int MONDAY 2 (월요일)
static int TUESDAY 3 (화요일)
static int WEDNESDAY 4 (수요일)
static int THURSDAY 5 (목요일)
static int FRIDAY 6 (금요일)
static int SATURDAY 7 (토요일)

 

■ Calendar 클래스의 메서드

반환타입 메서드 설명
static Calendar getInstance() 시스템의 현재 날짜와 시간으로 Calendar 인스턴스 반환
원하는 날짜나 시간으로 설정하려면 set 메서드 사용할 것
int get(int field) 인스터스에 담긴 정보를 필드(상수)값을 이용해서 반환
int getActualMaximum(int field) 특정한 달의  말일 구할 때 사용됨
ex)  getActualMaximum(Calendar.DATE)
void set(int field, int value) 원하는 날짜와 시간으로 변경
ex) set(Calendar.YEAR, 2020) → 2020년으로 변경
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)
원하는 날짜와 시간으로 변경
ex) set(2019, 12, 25, 5, 30, 25) → 2019년 12월 25일 5시 30분 25초로 변경
YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY, MINUTE, SECODN  필드(상수)값 대입
void clear()
void clear(int field)
모든 필드 초기화
필드값 지정시, 지정된 필드 값을 기본 값으로 초기화
각 필드의 기본값은 JAVA API 문서의 GregorianCalendar 참고 
long getTimeInMillis() 해당 인스턴스의 시간을 천분의 일초 단위로 변환후 반환 
1970년 1월 1일 이전 날짜에 대해서는 음수 값 반환
boolean after(Object when) 해당 인스턴스가 when 객체보다 시간이 이후면 true, 아니면 false
boolean before(Object when) 해당 인스턴스가 when 객체보다 시간이 이전이면 true, 아니면 false
abstract void add(int field, int amount) 지정한 필드값을 원하는 만큼 증가 또는 감소시킬 수 있음
지정된 필드값의 변경으로 다른 필드값에게도 영향을 줄 수 있음
ex) 일수를 추가해서 달이 바뀌는 경우 등등 
void roll(int field, int amount) 지정한 필드값을 원하는 만큼 증가 또는 감소시킬 수 있음
지정된 필드값의 변경으로 다른 필드값에게 영향 안줌
영향을 줄 수 있는 예외 : 필드값이 일(Calendar.DATE)필드 값이 말일(end of month)인데 roll()메서드를 통해 월(Calendar.MONTH) 필드 값 변경 시 일 필드 값이 바뀔 수 있음 (말일은 달마다 다르기 때문에)
Date getTime() Calendar를 Date 타입으로 변환
Calendar → Date
void setTime(Date date) Date인스턴스를 Calendar인스턴스로 변환
Date → Calendar

 

 

예제1

import java.util.Calendar;

class prac{
    public static void main (String[] args){
    	Calendar today = Calendar.getInstance();
    	
    	/* 년도 구하기 */
    	System.out.println(today.get(Calendar.YEAR));  // 2021
    	
    	/* 몇 월인지 구하기 (나온 값에 +1 해줘야함) */
    	System.out.println(today.get(Calendar.MONTH));  // 10   (11월 의미) 
    	
    	/* 일수 구하기 (= DAY_OF_MONTH 와 동일) */
    	System.out.println(today.get(Calendar.DATE));  // 8
    	
    	/* 일수 구하기 (= DATE 와 동일) */
    	System.out.println(today.get(Calendar.DAY_OF_MONTH));  // 8
    	
    	/* 요일 (1: 일요일, 2: 월요일, 3:화요일 .....) */ 
    	System.out.println(today.get(Calendar.DAY_OF_WEEK));  // 2
    	
    	/* 그 해의 몇 번째 일 */
    	System.out.println(today.get(Calendar.DAY_OF_YEAR));  // 312
    	
    	/* 이 달의 몇 번째 요일 */
    	System.out.println(today.get(Calendar.DAY_OF_WEEK_IN_MONTH));  // 2 (이 달의 둘 째주 요일)
    	
    	/* 오전/오후 구별 */
    	System.out.println(today.get(Calendar.AM_PM));  // 1
    	
    	/* 이번년에 몇 번째 주인지 구하기 */
    	System.out.println(today.get(Calendar.WEEK_OF_YEAR));  // 46
    	
    	/* 이번달에 몇 번째 주인지 구하기 */
    	System.out.println(today.get(Calendar.WEEK_OF_MONTH));  // 2

    	/* 이달의 마지막 일 구하기 */
    	System.out.println(today.getActualMaximum(Calendar.DATE));  // 30
    	
    	/* 현재 시간 구하기 */ 
    	System.out.println(today.get(Calendar.HOUR));  // 7
    	System.out.println(today.get(Calendar.MINUTE));  // 8
    	System.out.println(today.get(Calendar.SECOND));  // 5
    	
    	/* 1/1000초 (범위 : 0~999) */
    	System.out.println(today.get(Calendar.MILLISECOND));  // 257
    	
    	/* TimeZone (-12 ~ +12) */
    	System.out.println(today.get(Calendar.ZONE_OFFSET)/(60*60*1000));  // 9
    	
    } 
}

 

 

예제2  ㅡ 두 날짜간의 차이 구하기

import java.util.Calendar;

class prac{
    public static void main (String[] args) {
    	Calendar date1 = Calendar.getInstance();
    	Calendar date2 = Calendar.getInstance();  // 현재 날짜 (2021 11 08)
    	
    	
    	date1.set(2021,10,5); // 2021일 11월 5일,  date1.set(2021, NOVEMBER, 5) 와 같음
    	System.out.println(toString(date1));  // 2021년, 11월, 5일
    	System.out.println(differ(date1, date2));  // 259200초 또는 3일 차이
    	
    }
    public static String toString(Calendar date) {
    	return date.get(Calendar.YEAR) + "년, " + 
    			(date.get(Calendar.MONTH)+1) + "월, " + date.get(Calendar.DATE)+ "일";
    }
    
    public static String differ(Calendar date1, Calendar date2) {  // 두 날짜간의 차이 구하기
    	// 두 날짜간의 차이를 구하려면 천분의 일초 단위로 변환 해야함
    	long differSecond = (date1.getTimeInMillis() - date2.getTimeInMillis())/1000;
    	differSecond = Math.abs(differSecond);
    	
    	long differDay = differSecond /(60*60*24);
    	
    	return differSecond + "초 또는 " + differDay + "일 차이";
    }
    
}

두 날짜간의 차이를 구하기 위해서는 두 날짜의 최소단위인 초단위로 변경한 다음 그 차이를 구할 것

getTimeInMillis() 메서드를 통해서 1/1000초 값을 얻고 거기서 나누기 1000을 통해서 초 단위 값을 얻음

두 날짜간의 차이를 일 수로 계산하려면 두 날짜간의 차이의 초단위 값을 ( 24(시간) * 60(분) * 60(초) ) 값으로 나눌 것

 

 

예제3

import java.util.Calendar;

class prac{
    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(toString(time1));  // 10시 20분 30초
    	System.out.println(toString(time2));  // 20시 30분 10초
    
    	long difference = Math.abs(time2.getTimeInMillis() - time1.getTimeInMillis()) /1000;
    	System.out.println(difference + "초 차이");  // 36580초 차이
    	
    	
    	String tmp = "";
    	for(int i=0; i<TIME_UNIT.length; i++) {
    		tmp += difference/TIME_UNIT[i] + TIME_UNIT_NAME[i];
    		difference %= TIME_UNIT[i];
    	}
    	System.out.println(tmp);  // 10시간 9분 40초
    
    
    }
    
    public static String toString(Calendar time) {
    	return time.get(Calendar.HOUR_OF_DAY) + "시 " + 
            time.get(Calendar.MINUTE) +"분 " + time.get(Calendar.SECOND)+ "초";
    }
    
}

 

 

예제4 ㅡ add() 메서드와 roll() 메서드 비교

import java.util.Calendar;

class prac{
    public static void main (String[] args)  {
    	Calendar date = Calendar.getInstance();
    	
    	date.set(2015,07,31); 
    	System.out.println(toString(date));  // 2015년 8월 31일
    	
    	date.add(Calendar.DATE, 1);
    	System.out.println(toString(date));  // 2015년 9월 1일
    	
    	date.add(Calendar.MONTH, -6);
    	System.out.println(toString(date));  // 2015년 3월 1일
    	
    	date.add(Calendar.DATE, 31);
    	System.out.println(toString(date));  // 2015년 4월 1일
    	
    	// roll() 메서드 사용
    	date.roll(Calendar.DATE, 31);
    	System.out.println(toString(date));  // 2015년 4월 2일
    	
    	date.roll(Calendar.DATE, -5);
    	System.out.println(toString(date));  // 2015년 4월 27일
    	
    }
    public static String toString(Calendar date) {
    	return date.get(Calendar.YEAR) + "년 " +
    			(date.get(Calendar.MONTH)+1) + "월 " + date.get(Calendar.DATE) + "일";
    }
}

기본적으로 roll() 메서는 add()메서드와 달리 다른 필드값에 영향을 주지 않음.

 

 

예제5 ㅡ roll() 메서드의 필드값 영향 예외

import java.util.Calendar;

class prac{
    public static void main (String[] args)  {
    	Calendar date = Calendar.getInstance();
    	
    	date.set(2015, 0, 31);
    	System.out.println(toString(date));  // 2015년 1월 31일 
    	
    	date.roll(Calendar.MONTH, 1);
    	System.out.println(toString(date)); // 2015년 2월 28일
    	
    }
    public static String toString(Calendar date) {
    	return date.get(Calendar.YEAR) + "년 " +
    			(date.get(Calendar.MONTH)+1) + "월 " + date.get(Calendar.DATE) + "일";
    }
}

2015년 1월 31일에서 roll() 메서드를 통해서 월(Calendar.MONTH)필드 값을 1 증가시켰더니 2015년 2월 28일이 되어버림. 원래라면 roll() 메서드는 지정한 필드값 외에는 영향을 주지 않아서 2015년 2월 31일이 되어야하지만 2월에는 31일이 존재하지 않기 때문에 2월 말일인 2015년 2월 28일로 자동 변경됨

 

 

 

예제6 ㅡ 달력 만들기1

import java.util.Calendar;

class prac{
    public static void main (String[] args)  {
    	int year = 2021, month = 5;
    	int START_DAY_OF_WEEK =0;
    	int END_DAY =0;
    	
    	Calendar sDay = Calendar.getInstance();
    	
        // 월은 0 ~ 11의 값을 가지므로 1을 빼줘야함
    	sDay.set(year, month-1, 1);
    	
    	START_DAY_OF_WEEK = sDay.get(Calendar.DAY_OF_WEEK);
    	
    	END_DAY  = sDay.getActualMaximum(Calendar.DATE);
    	
    	System.out.println("       "+year + "년 " + month + "월");
    	System.out.println(" SU MO TU WE TH FR SA");
    	
    	for(int i=1; i<START_DAY_OF_WEEK;i++) {
    		System.out.print("   ");
    	}
    	
    	for(int i=1, n=START_DAY_OF_WEEK; i<=END_DAY; i++, n++) {
    		System.out.print((i<10)? "  "+ i : " " + i);
    		
    		if(n%7==0) System.out.println();
    	}
    	
    }
}

/* 출력값
       2021년 5월
 SU MO TU WE TH FR SA
                    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 31
*/

year와 month 값을 지정해줌으로써 특정 달력을 만듦

월(MONTH) 값을 Calendar 인스턴스 값에 대입할 때는 -1한 상태로 넣고 Calendar 인스턴스로부터 값을 반환 받을 때는 +1한 상태로 받을 것

 

 

 

예제 7 ㅡ 달력만들기2

import java.util.Calendar;

class prac{
    public static void main (String[] args)  {
    	int START_DAY_OF_WEEK =0;
    	int END_DAY =0;
    	
    	Calendar sDay = Calendar.getInstance();
    	int year = sDay.get(Calendar.YEAR);
    	int month = sDay.get(Calendar.MONTH) + 1;

    	START_DAY_OF_WEEK = sDay.get(Calendar.DAY_OF_WEEK);
    	END_DAY  = sDay.getActualMaximum(Calendar.DATE);
    	
    	System.out.println("       "+ year + "년 " + month + "월");
    	System.out.println(" SU MO TU WE TH FR SA");
    	
    	for(int i=1; i<START_DAY_OF_WEEK;i++) {
    		System.out.print("   ");
    	}
    	
    	for(int i=1, n=START_DAY_OF_WEEK; i<=END_DAY; i++, n++) {
    		System.out.print((i<10)? "  "+ i : " " + i);
    		
    		if(n%7==0) System.out.println();
    	}
    	
    }
}

/* 출력값
       2021년 11월
 SU MO TU WE TH FR SA
     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
*/

year와 month 값을 현재 날짜로 설정하여 이번달 달력을 만듦

월(MONTH) 값을 Calendar 인스턴스 값에 대입할 때는 -1한 상태로 넣고 Calendar 인스턴스로부터 값을 반환 받을 때는+1한 상태로 받을 것

 

 

 

예제8 ㅡ 달력만들기3

import java.util.Calendar;

class prac{
    public static void main (String[] args)  {
    	int year = 2021, month = 5;
    	
    	Calendar sDay = Calendar.getInstance();
    	Calendar eDay = Calendar.getInstance();
    	
    	sDay.set(year, month-1, 1);
    	eDay.set(year, month-1, sDay.getActualMaximum(Calendar.DATE));
    	
    	sDay.add(Calendar.DATE, -(sDay.get(Calendar.DAY_OF_WEEK)-1));
    	eDay.add(Calendar.DATE, 7-eDay.get(Calendar.DAY_OF_WEEK));
    	
    	System.out.println("       "+ year + "년 " + month + "월");
    	System.out.println(" SU MO TU WE TH FR SA");
    	
    	for(int n=1; sDay.before(eDay) || sDay.equals(eDay); sDay.add(Calendar.DATE, 1), n++) {
    		int day = sDay.get(Calendar.DATE);
    		
    		System.out.print(day <10? "  "+ day : " " + day);
    		if(n%7==0) System.out.println();
    	}
    	
    }
}

/* 출력값
       2021년 5월
 SU MO TU WE TH FR SA
 25 26 27 28 29 30  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 31  1  2  3  4  5
*/

달력의 첫 주와 마지막주가 이전달, 이후 달과 연결되도록 출력

 

 

예제9 ㅡ 년, 월 간단한 계산

import java.util.Calendar;
import java.util.Scanner;

class prac{
    public static void main (String[] args)  {
    	String date1="201508";
    	String date2="201405";
    	
    	int month1 = Integer.parseInt(date1.substring(0,4))*12 + Integer.parseInt(date1.substring(4));
    	int month2 = Integer.parseInt(date2.substring(0,4))*12 + Integer.parseInt(date2.substring(4));

    	System.out.println(Math.abs(month2-month1)); // 15
    }
}

간단한 계산이면 Calendar를 사용하지 않고도 가능

 

 

예제10

import java.util.Calendar;

class prac{
    public static void main (String[] args)  {
    	System.out.println(getDayOfWeek(2014,5,31));  // 7
    	System.out.println(getDayOfWeek(2012,6,1));  // 6
    	
    	System.out.println(dayDiff(2014,5,1,2014,4,28));  // 3
    	
    	System.out.println(convertDateToDay(2015,6,29));  // 735778
    	System.out.println(convertDayToDate(735778));  // 2015-6-29
    }
    
    static int[] endOfMonth = {
    		31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    
    static boolean isLeapYear(int year) {  // 윤년 판별
    	return (year%4==0) && (year%100!=0) || (year%400==0);
    }
    
    static int dayDiff(int y1, int m1, int d1, int y2, int m2, int d2) {  // 두 날짜간의 차이를 일단위로 반환
    	return convertDateToDay(y1,m1,d1) - convertDateToDay(y2,m2,d2); 
    }
    
    static int getDayOfWeek(int year, int month, int day) {  // 지정한 날짜의 요일 반환 
    	Calendar date = Calendar.getInstance();
    	date.set(year, month-1, day);
    	return date.get(Calendar.DAY_OF_WEEK);
    }

    static String convertDayToDate(int day) {  // 일단위의 값을 년월일의 형태의 문자열로 변환하여 반환
    	int year = 1;
    	int month = 0;
    	while(true) {
    		int aYear = isLeapYear(year) ? 366 : 365;
    		if (day > aYear) {
    			day -= aYear;
    			year++;
    		} else break;
    	}
    	
    	while(true) {
    		int endDay = endOfMonth[month];
    		if(isLeapYear(year) && month ==1) endOfMonth[month] ++;
    		
    		if(day > endDay) {
    			day -= endDay;
    			month++;
    		} else break;
    	}
    	
    	return year + "-"+ (month+1) + "-" + day;
    }

    static int convertDateToDay(int year, int month, int day) {  // 년월일을 입력받아서 일단위로 변환
    	
    	int lastYearDay = 0;
    	int countLeapYear = 0;
    	for(int i=1; i<year-1; i++) {
    		if(isLeapYear(i)) {
    			countLeapYear++;
    		}
    	}
    	lastYearDay = (year-1)*365 + countLeapYear;
    	
    	int nowYearDay = 0;
    	for (int i=0; i<month-1; i++) nowYearDay += endOfMonth[i];
    	
    	if(isLeapYear(year)) nowYearDay++;
    	
    	return lastYearDay + nowYearDay + day;
    }
    
    
}

 

 

 


 

 

 

▒ 형식화 클래스

  • java.text 패키지에 포함되어 있음
  • 숫자, 날짜, 텍스트 데이터를 일정한 형식에 맞춰 표현할 수 있는 방법을 객체지향적으로 설계하여 표준화함
  • 형식화 클래스는 형식화에 사용될 패턴을 정의하는데, 데이터를 정의된 패턴에 맞춰 형식화할 수 있을 뿐만 아니라 역으로 형식화된 데이터에서 원래의 데이터를 얻어낼 수도 있음
  • 형식화된 데이터의 패턴만 정의해주면 복잡한 문자열에서도 substring()메서드를 사용하지 않고도 쉽게 원하는 값 추출 가능

 

◎ DecimalFormat

  • 숫자를 다양한 형식(패턴)으로 출력할 수 있음
  • 숫자 데이터를 정수, 부동소수점, 금액 등 다양한 형식으로 표현 가능, 반대로 일정한 형식의 텍스트 데이터를 숫자로 변환 가능
  • 숫자 → 형식 문자열, 형식 문자열 → 숫자 둘 다 가능 
  • import java.text.DecimalFormat; 쓸 것
  • new 연산자를 이용해서 인스턴스 생성

 

기호 의미 패턴 결과(1234567.89)
0 10진수
(값이 없는 자리는 0으로 채움)
'0' 은 표시한 자리수만큼 값을 최소한 표시
0
0.0
000000000.0000
1234568
1234567.9
0001234567.8900
# 10진수
(값이 없는 자리는 나타내지 않음)
#은 표시한 소수점자리수만큼 반올림하여 표시
#
#.#
##########.####
12345678
1234567.9
1234567.89
. 소수점 #.# 1234567.9
-
+
음수부호
양수부호
#.#-
-#.#
#.#+
+#.#
1234567.9-
-1234567.9
1234567.9+
+1234567.9
, 단위 구분자 #,###.##
#,####.##
1,234,567.89
123,4567.89
E 지수기호 #E0
0E0
##E0
00E0
###E0
000E0
#.#E0
0.0E0
0.000000000E0
00.00000000E0
000.0000000E0
#.#########E0
##.########E0
###.#######E0
.1E7
1E6
1.2E6
12E5
123.5E4
1235E3
1.2E6
1.2E6
1.234567890E6
12.34567890E5
123.4567890E4
1.23456789E6
1.23456789E6
1.23456789E6
; 패턴 구분자
양수와 음수의 패턴을 모두 기술할 경우, 패턴 구분자
#,##.##+;#,###.##- 1,234,567.89+ (양수일 때)
1,234,567.89- (음수일 때)
% 퍼센트 (100을 곱하고 % 붙임) #.#% 123456789%
\u2030 퍼밀(퍼센트 * 10) #.#\u2030 1234567890%
\u00A4 통화 \u00A4 #,### \ 1,234,568
' escape문자 '#'#.###
"#,###
#1,234,568
'1,234,568

 

 

 

 

예제1

import java.text.DecimalFormat;

public class prac {
	public static void main(String[] args){
		double number = 1234567.89;
		DecimalFormat df = new DecimalFormat("#.#E0");
		String result = df.format(number);
		System.out.println(result);  // 1.2E6
	}
}

 

 

예제2

import java.text.DecimalFormat;


class prac{
    public static void main (String[] args)  {
    	double number = 1234567.89;
    	String[] pattern = {
    			"0",    
    			"#",  
    			"0.0",  
    			"#.#", 
    			"0000000000.0000", 
    			"##########.####",
    			"#.#-",  
    			"-#.#", 
    			"#,##.##",  
    			"#,###.##",  
    			"#E0",  
    			"#0E0",
    			"##E0",
    			"00E0",
    			"####E0",
    			"0000E0",
    			"#.#E0",
    			"0.0E0",
    			"0.000000000E0",
    			"00.00000000E0",
    			"000.0000000E0",
    			"#.#########E0",
    			"##.########E0",
    			"###.#######E0",
    			"#,###.##+;#,###.##-",
    			"#.#%",
    			"#.#\u2030",
    			"\u00A4 #,###",
    			"'#'#,###",
    			"''#,###"
    	};
    	
    	for(int i=0; i< pattern.length; i++) {
    		DecimalFormat df = new DecimalFormat(pattern[i]);
    		System.out.printf("%19s : %s\n", pattern[i], df.format(number));
    	}
    	
    }
    
}

/* 출력값
                  0 : 1234568
                  # : 1234568
                0.0 : 1234567.9
                #.# : 1234567.9
    0000000000.0000 : 0001234567.8900
    ##########.#### : 1234567.89
               #.#- : 1234567.9-
               -#.# : -1234567.9
            #,##.## : 1,23,45,67.89
           #,###.## : 1,234,567.89
                #E0 : .1E7
               #0E0 : 1.2E6
               ##E0 : 1.2E6
               00E0 : 12E5
             ####E0 : 123.5E4
             0000E0 : 1235E3
              #.#E0 : 1.2E6
              0.0E0 : 1.2E6
      0.000000000E0 : 1.234567890E6
      00.00000000E0 : 12.34567890E5
      000.0000000E0 : 123.4567890E4
      #.#########E0 : 1.23456789E6
      ##.########E0 : 1.23456789E6
      ###.#######E0 : 1.23456789E6
#,###.##+;#,###.##- : 1,234,567.89+
               #.#% : 123456789%
               #.#‰ : 1234567890‰
            ¤ #,### : ₩ 1,234,568
           '#'#,### : #1,234,568
            ''#,### : '1,234,568
*/

 

 

예제3

import java.text.DecimalFormat;
import java.text.ParseException;


class prac{
    public static void main (String[] args)   {
    	DecimalFormat df = new DecimalFormat("#,###.##");
    	DecimalFormat df2 = new DecimalFormat("#.###E0");
    	
    	try {
    		Number num = df.parse("1,234,567.89");  // 기호와 문자가 포함된 문자열이 숫자로 변환
    		System.out.println(num);  // 1234567.89
    	
    		double d = num.doubleValue();  // double 타입으로 변환
    		System.out.println(d);  // 1234567.89
    		
    		System.out.println(df2.format(num));  // 1.235E6

    		
    	} catch (ParseException e) {}
    	
    }
    
}

parse(String source) 메서드를 통해 기호와 문자가 포함된 문자열을 숫자로 변환할 수 있고 반환타입은 Number 클래스타입

parse() 메서드는 DecimalFormat의 조상인 NumberFormat 클래스에 정의된 메서드 

parse()메서드 ParseException 예외가 발생할 수 있어 예외처리 필수

parseException 예외가 발생할 때는 import java.text.ParseException; 쓸 것. 단, catch문에 Exception으로 대체한다면 import문 안써도 됨

Integer.parseInt메서드는 콤마(,)가 포함된 문자열을 숫자로 변환 못함

 

 

 


 

SimpleDateFormat 클래스

  • 날짜와 시간을 다양한 형식으로 출력할 때 사용
  • Date 클래스와 Calendar 클래스만으로 날짜 데이터를 원하는 형태로 다양하게 출력하는것은 불편하고 복잡
  • DateFormat은 추상클래스로 SimpleDateFormat의 조상 클래스
  • DateFormat 인스턴스를 생성하기 위해서는 getDateInstance() 메서드 사용할 것
    • getDateInstance() 메서드를 통해 반환된 것은 DateFormat을 상속받아 완전하게 구현한 SimpleDateFormat 인스턴스
    • DateFormat 사용시 import java.text.DateFormat; 쓸 것
  • import java.text.SimpleDateFormat; 쓸 것
  • 먼저 원하는 출력 형식의 패턴을 작성하여 SimpleDateFormat 인스턴스를 생성한 다음, 출력하고자 하는 Date 인스턴스를 가지고 format(Date d)를 호출하면 지정한 출력형식에 맞게 변환된 문자열을 얻음

 

 

기호 의미 보기
G 연대(BC, AD) AD
y 년도 2006
M 월(1~12 또는 1월~12월) 10 또는 10월, OCT
w 년의 몇 번째 주 (1~53) 50
W 월의 몇 번째 주(1~5) 4
D 년의 몇 번째 일(1~366) 100
d 월의 몇번째 일(1~31) 15
F 월의 몇 번째 요일(1~5) 1
E 요일 
a 오전/오후 (AM,PM) PM
H 시간 (0~23) 20
k 시간 (1~24)  (잘 안쓰임) 13
K 시간 (0~12) (잘 안쓰임) 10
h 시간 (1~12) 11
m 분 (0~59) 35
s 초 (0~59) 55
S 천분의 일초 (0~999) 253
z Time zone (General time zone) GMT+9:00
Z Time zone (RFC 822 time zone) +0900
' escape문자 (특수문자를 표현하는데 사용) 없음

 

 

DateFormat 클래스

  • 추상클래스이며 SimpleDateFormat 조상 클래스

 

■ DateFormat 클래스 메서드

반환타입 메서드 설명
DateFormat getDateInstance() DateFormat 인스턴스 생성
Date parse(String source) 문자열 source를 날짜 Date 인스턴스로 변환
String format(Date date) Date에 저장된 날짜값을 문자열로 변환

 

 

예제1

import java.util.Date;
import java.text.SimpleDateFormat;

class prac{
    public static void main (String[] args)  {
    	Date today = new Date();
    	SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); // 오늘 날짜를 yyyy-MM-dd 형태로 변환
    	
    	String result = df.format(today);
    	System.out.println(result);  // 2021-11-10
    	
    }
}

 

 

예제2

import java.util.Date;
import java.text.SimpleDateFormat;

class prac{
    public static void main (String[] args)  {
    	Date today = new Date();
    	
    	SimpleDateFormat sdf1, sdf2, sdf3, sdf4;
    	SimpleDateFormat sdf5, sdf6, sdf7, sdf8, sdf9;
    	
    	sdf1 = new SimpleDateFormat("yyyy-MM-dd");
    	sdf2 = new SimpleDateFormat("''yy년 MMM dd일 E요일");
    	sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mmss.SSS");
    	sdf4 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a");
    	
    	
    	sdf5 = new SimpleDateFormat("오늘은 올해의 D번째 날입니다");
    	sdf6 = new SimpleDateFormat("오늘은 이달의 d번째 날입니다");
    	sdf7 = new SimpleDateFormat("오늘은 올해의 w번째 주입니다");
    	sdf8 = new SimpleDateFormat("오늘은 이달의 W번째 주입니다");
    	sdf9 = new SimpleDateFormat("오늘은 이달의 F번째 E요일입니다");
    	
    	System.out.println(sdf1.format(today));
    	System.out.println(sdf2.format(today));
    	System.out.println(sdf3.format(today));
    	System.out.println(sdf4.format(today));
    	System.out.println();
    	
    	System.out.println(sdf5.format(today));
    	System.out.println(sdf6.format(today));
    	System.out.println(sdf7.format(today));
    	System.out.println(sdf8.format(today));
    	System.out.println(sdf9.format(today));
    	
    	
    }
}
/* 출력값
2021-11-10
'21년 11월 10일 수요일
2021-11-10 19:3747.214
2021-11-10 07:37:47 오후

오늘은 올해의 314번째 날입니다
오늘은 이달의 10번째 날입니다
오늘은 올해의 46번째 주입니다
오늘은 이달의 2번째 주입니다
오늘은 이달의 2번째 수요일입니다
*/

 

 

예제3

import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Calendar;
class prac{
    public static void main (String[] args)  {
    	Calendar cal = Calendar.getInstance();
    	cal.set(2005, 10, 3);
    	
    	Date day = cal.getTime();  // Calendar를 Date로 변환
    	
    	SimpleDateFormat sdf1, sdf2, sdf3, sdf4;
    	
    	sdf1 = new SimpleDateFormat("yyyy-MM-dd");
    	sdf2 = new SimpleDateFormat("yy-MM-dd E요일");
    	sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    	sdf4 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a");
    	
    	System.out.println(sdf1.format(day));  // 2005-11-03
    	System.out.println(sdf2.format(day));  // 05-11-03 목요일
    	System.out.println(sdf3.format(day));  // 2005-11-03 20:29:54.651
    	System.out.println(sdf4.format(day));  // 2005-11-03 08:29:54 오후
    }
}

Date인스턴스만 format메서드에 사용될 수 있기에 Calendar 인스턴스를 Date인스턴스로 변환함

 

예제4

import java.util.Date;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
class prac{
    public static void main (String[] args) throws ParseException  {
    	
    	DateFormat df = new SimpleDateFormat("yyyy년 MMM dd일");
    	DateFormat df2 = new SimpleDateFormat("yyyy/MM/dd");
    	
    	try {
    		Date d = df.parse("2015년 11월 23일");
    		System.out.println(df2.format(d));  // 2015/11/23
    	} catch(ParseException e) {}
    	
    	
    }
}

parse(String source) 메서드를 사용하여 날짜 데이터의 출력형식을 변환

parse(String source) 메서드는 문자열 source를 날짜 Date인스턴스로 변환해줌

 

 

예제5

import java.util.*;
import java.text.*;

class prac{
    public static void main (String[] args) {
    	
    	String pattern = "yyyy/MM/dd";
    	DateFormat  sdf = new SimpleDateFormat(pattern);

    	Scanner s = new Scanner(System.in);
    	
    	Date date = null;
    	
    	System.out.println(pattern + " 형식으로 입력하시오");
    	while(s.hasNextLine()) {
    		try {
    			date = sdf.parse(s.nextLine());
    			break;
    		} catch(ParseException e) {
    			System.out.println("다시 입력하시오");
    		}
    		
    	}
    	
    	Calendar cal = Calendar.getInstance();
    	cal.setTime(date);
    	
    	Calendar today = Calendar.getInstance();
    	
    	long day = (cal.getTimeInMillis() - today.getTimeInMillis())/ (60*60*1000);
    	System.out.println(day);
    	
    	
    }
}

/* 출력값
yyyy/MM/dd 형식으로 입력하시오
2021/11/12
24
*/

 

 

 


 

◎ ChoiceFormat

  • 특정 범위에 속하는 값을 문자열로 변환
  • 연속적 또는 불연속적인 범위의 값들을 처리하는 데 있어서 if문이나 switch문은 적절하지 못한 경우가 많은데 ChoiceFormat으로는 잘 처리할 수 있음
  • import java.text.ChoiceFormat; 쓸 것

 

 

■ 생성자

ChoiceFormat form = new ChoiceFormat(double[] limits, String[] formats)


ChoiceFormat form = new ChoiceFormat(String newPattern)

 

 

 

◎ NumberFormat

  • 추상클래스이며, ChoiceFormat 클래스와 DecimalFormat 클래스의 조상 클래스

 

 메서드

반환타입 메서드 설명
String format(double number)
String format(long number)
문자열로 변환
NumberFormat getInstance() NumberFormat 인스턴스 반환

 

 

 

예제1

import java.text.ChoiceFormat;

class prac{
    public static void main (String[] args) {
    	double[] limits = {60, 70, 80, 90};  // 낮은순으로 적을 것
    	String[] grades = {"D", "C", "B", "A"};
    	
    	int[] scores = {100, 95, 88, 70, 52, 60, 70};
    	
    	ChoiceFormat form = new ChoiceFormat(limits, grades);
    	
    	for(int i=0; i<scores.length; i++) {
    		System.out.println(scores[i] + " : " + form.format(scores[i]));
    	}
    	
    }
}

/* 출력값
100 : A
95 : A
88 : B
70 : C
52 : D
60 : D
70 : C
*/

두 개의 배열이 사용되었는데 하나(limits)는 범위의 경계값을 저장하는데 사용했고, 또 하나는(grades)는 범위에 포함된 값을 치환할 문자열을 저장하는데 사용

경계값은 double형으로 반드시 모두 오름차순으로 정렬되어 있어야하며, 치환 될 문자열의 개수는 경계값에 의해 정의된 범위의 개수와 일치해야함. 그렇지 않으면 IllegalArgumentException 예외 발생

위 예제에서 경계값은 '60~69', '70~79', '80~89', '90~' 범위가 정의됨

 

 

 

예제2

import java.text.ChoiceFormat;

class prac{
    public static void main (String[] args) {
    	String pattern = "60#D|70#C|80<B|90#A";
    	int[] scores = {91, 90, 80, 88, 70 ,52, 60};
    	
    	ChoiceFormat form = new ChoiceFormat(pattern);
    	
    	for(int i=0; i<scores.length; i++) {
    		System.out.println(scores[i] + " : " + form.format(scores[i]));
    	}
    	
    }
}

/* 출력값
91 : A
90 : A
80 : C
88 : B
70 : C
52 : D
60 : D
*/

배열대신 패턴을 사용하는것이 더 간결하게 처리 가능

패턴은 구분자로 '#'과 '<' 두가지를 제공하는데 'limit#value'의 형태로 사용

'#'은 경계값을 범위에 포함시키지만, '<'는 경계값을 포함시키지 않음

'61#D|71#C|81#B|91#A' 보다 '60<D|70<C|<80<B|90<A' 가 더 직관적이다  

 


 

 

◎ MessageFormat

  • 데이터를 정해진 양식에 맞게 출력할 수 있게 도와줌
  • 특정 형식을 가진 문자열에서 데이터를 뽑아낼 때 유용
  • 데이터가 들어갈 자리를 마련해 놓은 양식을 미리 작성하고 프로그램을 이용해서 다수의 데이터를 같은 양식으로 출력할 때 사용
  • SimpleDateFormat클래스의 parse() 메서드처럼 MessageFormat 클래스도 parse()메서드를 이용하면 지정된 양식에서 필요한 데이터만 추출 가능
  • import java.text.MessageFormat; 쓸 것

 

예제1

import java.text.MessageFormat;

class prac{
    public static void main (String[] args) {
    	String msg = "Name: {0} \nTel: {1} \nAge: {2} \nBirthday: {3}";
    	
    	Object[] arguments = {
    			"이자바", "02-123-1234", "27", "07-09"
    	};
    	
    	String result = MessageFormat.format(msg, arguments);
    	System.out.println(result);
    }
    
}

/* 출력값
Name: 이자바 
Tel: 02-123-1234 
Age: 27 
Birthday: 07-09
*/

MessageFormat에 사용할 양식인 문자열 msg를 작성할 때 '{숫자}'로 표시된 부분이 데이터가 출력될 자리

이 자리는 순차적일 필요는 없고 여러 번 반복해서 사용 가능

해당 자리에 객체배열인 arguments에 이정된 값이 자리에 맞게 값이 들어감

 

 

 

 

 

예제2

import java.text.MessageFormat;

class prac{
    public static void main (String[] args) {
    	String msg = "Values (''{0}'', ''{1}'', ''{2}'', ''{3}'')";
    	
    	Object[][] arguments = {
    			{"이자바", "02-123-1234", "27", "07-09"},
    			{"김프로", "032-333-1234", "33", "10-07"}
    	};
    	
    	for(int i=0; i<arguments.length; i++) {
    		String result = MessageFormat.format(msg, arguments[i]);
    		System.out.println(result);
    	}
    	
    }
}

/* 출력값
Values ('이자바', '02-123-1234', '27', '07-09')
Values ('김프로', '032-333-1234', '33', '10-07')
*/

반복만으로 하나 이상의 데이터 집합을 출력

 

 

예제3

import java.text.MessageFormat;
import java.text.ParseException;

class prac{
    public static void main (String[] args) throws ParseException{
    	String[] data = {
    			"Value('이자바', '02-123-1234', '27', '07-09')",
    			"Value('김프로', '032-333-1234', '33', '10-07')"
    	};
    	
    	String pattern = "Value({0}, {1}, {2}, {3})";
    	
    	MessageFormat mf = new MessageFormat(pattern);
    	
		for(int i=0; i<data.length; i++) {
			Object[] objs = mf.parse(data[i]);
			
			for(int j=0; j<objs.length; j++) {
				System.out.print(objs[j]);
			}
			
			System.out.println();
		}
    	
    }
}

/* 출력값
'이자바''02-123-1234''27''07-09'
'김프로''032-333-1234''33''10-07'
*/

parse(String source)를 이용해서 출력된 데이터로부터 필요한 데이터만 뽑아냄

 

 

예제4

/* data1.txt */
'이자바', '02-123-1234', '27', '07-09'
'김프로', '032-333-1234', '33', '10-07'
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.text.MessageFormat;
import java.text.ParseException;

class prac{
    public static void main (String[] args) throws FileNotFoundException, ParseException{
    	
    	String tableName = "Info";
    	String msg = "Insert "+ tableName + " Values ({0}, {1}, {2}, {3})";
    	String fileName = "data1.txt";
    	
    	Scanner s = new Scanner(new File(fileName));
    	String pattern = "{0}, {1}, {2}, {3}";
    	
    	MessageFormat mf = new MessageFormat(pattern);

    	while(s.hasNextLine()) {
    		String line = s.nextLine();
    		Object[] objs = mf.parse(line);
    		String result = MessageFormat.format(msg, objs);
    		System.out.println(result);
    	}
    	
    }
}


/* 출력값
Insert Info Values ('이자바', '02-123-1234', '27', '07-09')
Insert Info Values ('김프로', '032-333-1234', '33', '10-07')
*/

Scanner를 통해서 파일로부터 데이터를 라인별로 읽어옴

 

 


 

▒ java.time 패키지

  • Date클래스와 Calendar클래스의 단점을 보완하기 위해 추가된 패키지
  • time 패키지에 속한 클래스들은 모두 불변(immutable)
    • 값 변경시 메모리에 새로운 인스턴스가 생성된다는 의미
    • 멀티 쓰레드 환경에서 안전
    • 멀티 쓰레드 환경에서는 동시에 여러 쓰레드가 같은 객체에 접근할 수 있기 때문에, 변경 가능한 객체는 데이터가 잘못될 가능성이 있어 쓰레드에 안전(thread-safe)하지 않음
  • time 패키지가 도입되어도 기존 작성된 프로그램과의 호환성 때문에 Date 클래스와 Calendar클래스는 여전히 사용중
  • time 패키지 쓸 것을 권장
  • 날짜와 시간을 하나로 표현하는 Calendar 클래스와 달리 time 패키지는 날짜와 시간을 별도의 클래스로 분리
  • 시간을 표현할 때는 LocalTime 클래스 사용
  • 날짜를 표현할 때는 LocalDate 클래스 사용
  • 시간과 날짜 모두 표현할 때는 LocalDateTime 클래스 사용
  • 시간, 날짜, 시간대(time-zone)을 모두 표현하려면 ZonedDateTime 클래스 사용
    • Calendar 클래스는 ZonedDateTime 클래스와 기능 유사
  • 날짜간의 차이는 Period 클래스 사용
  • 시간의 차이는 Duration 클래스 사용  
  • java.Time.Instant 클래스는 Date 클래스와 기능 유사
  • Instant클래스는 날짜와 시간을 초 단위(나노초)로 표현 
    • 날짜와 시간을 초단위로 표현한 값을 타임스탬프(time-stamp)라고 부름
    • 타임스탬프는 날짜와 시간을 하나의 정수로 표현한 것이므로 날짜와 시간의 차이를 계산하거나 순서를 비교할 때 유리해서 데이터베이스에 많이 사용됨
  • 날짜를 더 세부적으로다룰 수 있는 Year, YearMonth, MonthDay와 같은 클래스 존재

 

 

java.tim패키지와 서브 패키지들

 

 

 

■ time 패키지 객체 생성 ㅡ now(), of()

  • java.time패키지에 속한 클래스의 객체를 생성하는 가장 기본적인 방법은 now()와 of() 사용하는 것
  • now() 메서드는 현재 날짜와 시간을 저장하는 객체 생성
  • of() 메서드는 값을 지정할 수 있으며 각 클래스마다 다양한 종류로 정의되어 있어 필드값을 순서대로 대입하면 됨

 

 

예제1 ㅡ now() 메서드로 객체 생성

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZonedDateTime;

class prac{
    public static void main (String[] args) {
    	LocalDate date = LocalDate.now();
    	LocalTime time = LocalTime.now();
    	LocalDateTime dateTime = LocalDateTime.now();
    	ZonedDateTime dateTimeInKr = ZonedDateTime.now();
    	
    	System.out.println(date);              // 2021-11-11
    	System.out.println(time);              // 11:21:53.349
    	System.out.println(dateTime);          // 2021-11-11T11:21:53.349
    	System.out.println(dateTimeInKr);      // 2021-11-11T11:21:53.349+09:00[Asia/Seoul]
    	
    }
}

 

 

예제2 ㅡ of() 메서드로 객체 생성

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

class prac{
    public static void main (String[] args) {
    	LocalDate date = LocalDate.of(2015,11, 23);
    	LocalTime time = LocalTime.of(23,59, 59);
    	LocalDateTime dateTime = LocalDateTime.of(date, time);
    	ZonedDateTime zDateTime = ZonedDateTime.of(dateTime, ZoneId.of("Asia/Seoul"));

    	System.out.println(date);           // 2015-11-23
    	System.out.println(time);           // 23:59:59
    	System.out.println(dateTime);       // 2015-11-23T23:59:59
    	System.out.println(zDateTime);      // 2015-11-23T23:59:59+09:00[Asia/Seoul]
    	
    }
}

 

 

 

 

◎ Temporal

  • 인터페이스
  • 날짜와 시간을 표현하는 클래스LocalDate, LocalTime, LocalDateTime, ZonedDateTime 들은 모두 Temporal, TemporalAccessor, TemporalAdjuster 인터페이스를 구현한 것
  • 메서드의 매개변수타입이 Temporal로 시작하는것들이 자주 등장할텐데 대부분 날짜와 시간을 위한 것이며. TemporalAmount인지 아닌지만 구분할 것

 

◎ TemporalAmount

  • 인터페이스
  • 날짜와 시간의차이를 표현하는 클래스Period, Duration 들은 모두 TemporalAmount 인터페이스를 구현한 것

 

 

 

◎ TemporalUnit

  • 날짜와 시간의 단위를 정의해놓은 인터페이스
  • TemporalUnit 인터페이스를 구현한 것이 열거형 ChronoUnit 클래스
    • 열거형(enumeration)은 서로 관련된 상수를 묶어서 정의해놓은 것

 

TemporalUnit(ChronoUnit) 설명
FOREVER Long.MAX_VALUE초 (약 3천억년)
ERAS 1,000.000.000년
MILLENNIA 1,000년
CENTURIES 100년
DECADES 10년
YEARS
MONTHS
WEEKS
DAYS
HALF_DAYS 반나절
HOURS
MINUTES
SECONDS
MILLIS 천분의 일초 (= 10^-3)
MICROS 백만분의 일초 (= 10^-6)
NANOS 10억분의 일초 (=10^-9)

 

 

 

 

◎ TemporalField

  • 년, 월, 일 등 날짜와 시간의 필드를 정의해놓은 인터페이스
  • TemporalField 인터페이스를 구현한 것은 열거형 ChronoField 클래스

 

타입 TemporalField(ChronoField) 설명
int ERA 시대
int YEAR_OF_ERA
YEAR
int MONTH_OF_YEAR
int DAY_OF_WEEK 요일  (1:월요일, 2: 화요일, .... 7: 일요일)
int DAY_OF_MONTH
int AMPM_OF_DAY 오전/오후
int HOUR_OF_DAY 시간(0~23)
int CLOCK_HOUR_OF_DAY 시간(1~24)
int HOUR_OF_AMPM 시간(0~11)
int CLOCK_HOUR_OF_AMPM 시간(1~12)
intint MINUTE_OF_HOUR
int SECOND_OF_MINUTE
int MILLI_OF_SECOND 천분의 일초 (= 10^-3 초) 
long MICRO_OF_SECOND 백만분의 일초 (= 10^-6 초)
long NANO_OF_SECOND 10억분의 일초 (= 10^-9 초)
int DAY_OF_YEAR 그 해의 몇번째 날
int EPOCH_DAY EPOCH(1970.1.1)로 부터 몇 번째 날
int MINUTE_OF_DAY 그 날의 몇 번째 분 (시간을 분으로 환산)
int SECOND_OF_DAY 그 날의 몇 번째 초 (시간을 초로 환산)
int MILLI_OF_DAY 그 날의 몇 번째 밀리초 (= 10^-3 초)
long MICRO_OF_DAY 그 날의 몇 번째 마이크로초 (= 10^-6 초)
long NANO_OF_DAY 그 날의 몇 번째 나노초 (= 10^-9 초)
int ALIGNED_WEEK_OF_MONTH 그 달의 n번째 주
(1~7일 →1주, 8~14일 → 2주, .....)
int ALIGNED_WEEK_OF_YEAR 그 해의 n번째 주
(1월 1~7일 1주, 1월 8~14 2주, .....)
int ALIGNED_DAY_OF_WEEK_IN_MONTH 요일 (그 달의 1일을 월요일로 간주하여 계산)
int ALIGNED_DAY_OF_WEEK_IN_YEAR 요일 (그 해의 1월1일을 월요일로 간주하여 계산)
int INSTANT_SECONDS 년월일을 초단위로 환산. Instant에만 사용 가능
(1970-01-01 00:00:00 UTC를 0로 계산)
int OFFSET_SECONDS UTC와의 시차. ZoneOffset에만 사용 가능
int PROLEPTIC_MONTH 년월을 월단위로 환산
ex)2015년 11월 → (2015*12) + 11
  • ChronoFeild의 상수를 사용할 수 있는 클래스는 서로가 다 다름
  • LocalDate 는 날짜를 표현하기 위한것이므로, MINUTE_OF_HOUR 와 같이 시간에 관련된 상수는 사용 못함
  • 해당 클래스가 지원하지 않는 필드를 사용하면 UnSupportedTemporalTypeException 예외 발생
  • 특정 상수가 가질수 있는 값의 범위를 알고 싶으면 range() 메서드를 사용할 것

 

System.out.println(ChronoField.CLOCK_HOUR_OF_DAY.range());   // 1-24
System.out.println(ChronoField.HOUR_OF_DAY.range());         // 0 -23

 

    

예제1

import java.time.LocalTime;
import java.time.temporal.ChronoField;

class prac{
    public static void main (String[] args) {
    	LocalTime now = LocalTime.now();
    	int minute = now.getMinute();
    	System.out.println(minute);  // 49
    	
    	int minute2 = now.get(ChronoField.MINUTE_OF_HOUR);
    	System.out.println(minute2);  // 49
    }
}

LocalTime클래스의 메서드 중 getMinute()get(ChronoField.MINUTE_OF_HOUR)는 기능 동일

날짜와 시간에서 특정 필드의 값만 얻을 떄는 get() 메서드나 get으로 시작하는 메서드를 이용할 것

 

 

 

예제2

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

class prac{
    public static void main (String[] args) {
    	LocalDate today = LocalDate.now();
    	
    	LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS);
    	System.out.println(tomorrow);  // 2021-11-12
    	
    	LocalDate tomorrow2 = today.plusDays(1);
    	System.out.println(tomorrow);  // 2021-11-12
        
    }
}

LocalDate 클래스의 메서드 중 plus()plusDays()는 기능 동일

특정 날짜와 시간에서 지정된 단위의 값을 더하거나 뺄 때는 plus() 또는 minus() 메서드에 열거형ChronoUnit을 사용할 것

 

 

 

◎ LocalDate

  • java.time 패키지의 가장 기본적인 클래스
  • 날짜를 표현할 때 사용
  • now() 메서드 또는 of() 메서드를 통해 인스턴스 생성
  • LocalDate 클래스의 월(month) 값의 범위는 1~12 까지
    • Calendar 클래스는 월(month)값의 범위가  0~11 까지
  • LocalDate 클래스의 요일값의 범위는 1~7 (1: 월요일, 2: 화요일, 3: 일요일..... 7: 일요일)
    • Calendar 클래스의 요일 값의 범위는 1~7 (1: 일요일, 2: 월요일, 3: 화요일, ...... 7: 토요일)

 

■ LocalDate 클래스 상수

제어자 타입 상수 설명
static LocalDate MAX +999999999-12-31
static LocalDate MIN -999999999-01-01

 

■ LocalDate 클래스 메서드

제어자 반환타입 메서드 설명
static LocalDate of(int year, Month month, int dayOfMonth)
static LocalDate of(int year, int month, int dayOfMonth)
지정된 날짜 값을 가진 LocalDate 인스턴스 생성
static LocalDate now() 오늘 날짜 값을 가진 LocalDate 인스턴스 생성
static LocalDate ofYearDay(int year, int dayOfYear) 해당 연도에 몇 번째일 인지 지정
static LocalDate parse(CharSequence text)

static LocalDate parse(CharSequence text, DateTimeFormatter formatter)
문자열을 파싱하여 LocalDate 인스턴스 생성
매개변수를 "yyyy-MM-dd" 양식으로 적을 것

② formatter 양식에 맞게 문자열을 파싱하여 LocalDate 인스턴스 생성
int getYear() 년도(year)값 반환
int getMonthValue() 월(month)값 반환 
반환값 범위 : 1~12
Month getMonth() 월(month)값을 영어로 반환
ex) NOVEMBER
int getDayOfMonth 일(day)값 반환
int getDayOfYear() 같은 해의 1일1일부터 몇 번쨰 일
DayOfWeek getDayOfWeek() 요일값을 영어로 반환
ex) FRIDAY
int getDayOfWeek().getValue() 요일값 반환
1: 월요일, 2: 화요일, ....., 7: 일요일
int lengthOfMonth() 해당 달의 총 일수 (해당 달의 마지막 일) 
int legnthOfYear() 해당 년의 총 일 수
(윤년일 경우 366, 윤년이 아닐 경우 365)
boolean isLeapYear() 윤년 여부 확인
윤년이면 true, 아니면 false
long getLong(TemporalField field) 필드값을 long 타입으로 반환
int get(TemporalField field) 필드 값을 int 타입으로 반환
① LocalDate with(TemporalAdjuster adjuster)

② LocalDate with(TemporalField field, long newValue)
① adjuster값으로 바뀐 시간과 날짜값을 가진 ZonedDateTime 인스턴스 생성

② field값이 newValue값으로 바뀐 ZonedDateTime 인스턴스 생성
LocalDate withYear(int year) 년도(year)값 변경
LocalDate withMonth(int month) 월(month)값 변경
LocalDate withDayOfMonth(int dayOfMonth) 일(day)값 변경
LocalDate plus(long amountToAdd, TemporalUnit unit)
LocalDate plus(TemporalAmount amountToAdd)
지정된 unit값에 amountToAdd값을 더함
LocalDate plusYears(long yearsToAdd) 년도(year)값에 yearsToAdd값 더함 
LocalDate plusMonths(long monthsToAdd) 월(month)값에 monthToAdd값 더함
LocalDate plusDays(long daysToAdd) 일(day)값에 daysToAdd값 더함
LocalDate plusWeeks(long weeksToAdd) 주(week)값에 weeksToAdd값 더함
int compareTo(ChronoLocalDate other) 같으면1
other보다 이전이면 -1
other보다 이후면 1
boolean isAfter(ChronoLocalDate other) other보다 이후면 true
boolean isBefore(ChronoLocalDate other) other보다 이전이면 true
boolean isEqual(ChronoLocalDate other) 서로 같으면 true
boolean equals(Object obj) 서로 같으면 true
LocalDateTime atTime(int hour, int minute)

LocalDateTime atTime(int hour, int minute, int second)

LocalDateTime atTime(int hour, int minute, int second, int nanoOfSecond)

LocalDateTime atTime(LocalTime time)
LocalDateTime atTime(offsetTime time)
매개변수의 시간값을 추가한 LocalDateTime 인스턴스 생성
LocalDateTime atStrartOfDay() 자정 시간(00:00)을 추가한 LocalDateTime 인스턴스 생성
ZoneDateTime atStartOfDay(ZoneId zone) 매개변수의 시간대를 추가한 ZoneDateTime 인스턴스 생성
Period until(ChronoLocalDate endDateExclusive) endDateExclusive 날짜와 차이값을 가진 Period 인스턴스 생성 
long until(Temporal endDateExclusive, TemporalUnit unit) unit양식에 맞는 값을 뺸 값
long toEpochDay() 에포크날(1970-010-01)로 부터 날짜를 세어서 반환 
String format(DateTimeFormatter formatter) 지정된 형식에 맞게 문자열로 변환
  • getMonthVolue() 메서드와 getMonth().getValue() 메서드는 서로 같음
  • equals()메서드가 있는데 isEqual()메서드를 제공하는 이유는 연표(chronology)가 다른 두 날짜를 비교하기 위함
    • 모든 필드가 일치해야하는 equals()와 달리 isEqual()은 오직 날짜만 비교
  • toEpochDay() 메서드를 이용해서 Period 클래스를 사용하지 않고 둘 날짜간의 일수를 편리하게 계산할 수 있음. 단, 두 날짜 모두 Epoch Day(1970-01-01) 이후 날짜여야 함

 

 

예제1

import java.time.LocalDate;

class prac{
    public static void main (String[] args) {

    	LocalDate today = LocalDate.now();
    	LocalDate day = LocalDate.of(2021, 12, 31);
    	LocalDate day2 = LocalDate.ofYearDay(1900,365);   // 1900년도에 365번째 일 → 1900년 12월 12일
    	LocalDate day3 = LocalDate.parse("2015-05-07");
    	
    	System.out.println(today);     // 2021-11-11
    	System.out.println(day);       // 2021-12-31
    	System.out.println(day2);      // 1900-12-31
    	System.out.println(day3);      // 2015-05-07
    	
    }
}

 

 

예제2

import java.time.LocalDate;
import java.time.chrono.JapaneseDate;

class prac{
    public static void main (String[] args) {
    	LocalDate kDate = LocalDate.of(1999, 12, 31);
    	JapaneseDate jDate = JapaneseDate.of(1999, 12, 31);
    	
    	System.out.println(kDate.equals(jDate));    // false
    	System.out.println(kDate.isEqual(jDate));   // true
    	
    }
}

kDate와 jDate의 YEAR_OF_ERA가 다르기 때문에 equals() 메서드에서는 false 반환

 

 

◎ LocalTime

  • java.time 패키지의 가장 기본적인 클래스
  • 시간을 표현할 때
  • now() 메서드 또는 of() 메서드를 통해 인스턴스 생성

 

■ LocalTime 상수

제어자 타입 상수 설명
static LocalTime MAX 23:59:59.999999999
static LocalTime MIN 00:00
static LocalTime NOON 12:00 (정오)
static LocalTime MIDNIGHT 00:00 (자정)

 

■ LocalTime 클래스 메서드

제어자
반환타입
제어자 반환타입 메서드 설명
static
LocalTime
of(int hour, int min)

of(int hour, int min, int sec)

of(int hour, int min, int sec, int nanoOfSecond)
지정된 시간 값을 가진 LocalDate 인스턴스 생성
static
LocalTime
now() 현재 시간 값을 가진 LocalDate 인스턴스 생성
static
LocalTime
ofSecondOfDay(long secondOfDay) 0시 0분 0초부터 secondOfDay초가 지난 시간을 의미
0  ≤ secondOfDay < 86400    (하루는 86400초)
static
LocalTime
parse(CharSequence text)

parse(CharSequence text, DateTimeFormatter formatter)
문자열을 파싱하여 LocalTime 인스턴스 생성
매개변수를 "HH:mm:ss" 양식으로 적을 것 
(ss는 생략 가능)

DateTimeFormatter 양식에 맞게 문자열을 파싱하여 LocalTime 인스턴스 생성

int getHour()
int getMinute()
int getSecond()
int getNano() 나노초
long  getLong(TemporalField field) 필드값을 long 타입으로 반환
int get(TemporalField field) 필드 값을 int 타입으로 반환
LocalTime with(TemporalAdjuster adjuster)

with(TemporalField field, long newValue)
① adjuster값으로 바뀐 시간과 날짜값을 가진 ZonedDateTime 인스턴스 생성

② field값이 newValue값으로 바뀐 ZonedDateTime 인스턴스 생성

LocalTime withHour(int hour) 시 값 변경
LocalTime withMinute(int minute) 분 값 변경
LocalTime withSecond(int second) 초 값 변경
LocalTime withNano(int nanoOfSecond) 나노 초 값 변경
LocalTime plus(TemporalAmount amountToAdd)

plus(long amountToAdd, TemporalUnit unit)
지정된 unit값에 amountToAdd값을 더함
LocalTime plusHours(long hoursToAdd) 시 값에 hoursToAdd값 더함
LocalTime plusMinutes(long minutesToAdd) 분 값에 minutesToAdd값 더함
LocalTime plusSeconds(long secondsToAdd) 초 값에 secondsToAdd값 더함
LocalTime plusNanos(long nanosToAdd) 나노초 값에 nanosToAdd값 더함
LocalTime truncatedTo(TemporalUnit unit) 지정된 것보다 작은 단위의 필드를 0으로 만듦
int compareTo(LocalTime other) 같으면 0
other인스턴스보다 이전이면 -1
other인스턴스보다 이후면 1 
boolean  isAfter(LocalTime other) other보다 이후면 true
boolean  isBefore(LocalTime other) other보다 이전이면 true
LocalDateTime atDate(LocalDate date) 매개변수인 날짜값을 추가한 LocalDateTime 인스턴스 생성
OffsetTime atOffset(ZoneOffset offset) 매개변수인 offset값을 추가한 offsetTime 인스턴스 생성
long  until(Temporal endExclusive, TemporalUnit unit) 매개변수값을 가진 시간과의 차이 반환
int toSecondOfDay() 시간을 초단위로 변환
long toNanoOfDay() 시간을 나노초단위로 변환
String format(DateTimeFormatter formatter) 지정된 형식에 맞게 문자열로 반환
  • toSecondOfDay() 메서드 또는 toNanoOfDay()메서드를 통해서 Duration클래스를 사용하지 않고도 시간차이를 구할 수 있음

 

 

예제1

import java.time.LocalTime;

class prac{
    public static void main (String[] args) {
    	
    	LocalTime now = LocalTime.now();
    	LocalTime time = LocalTime.of(17, 30, 17);
    	LocalTime time2 = LocalTime.ofSecondOfDay(86399);   // 0시 0분 0초로부터 86399초가 지남 → 23시 59분 59초
    	LocalTime time3 = LocalTime.parse("14:25:30");
    	
    	System.out.println(now);     // 13:52:55.962 
    	System.out.println(time);    // 17:30:17
    	System.out.println(time2);   // 23:59:59
    	System.out.println(time3);   // 14:25:30
    	
    }
}

 

예제2

import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

class prac{
    public static void main (String[] args) {
    	LocalTime now = LocalTime.of(19, 21, 35);
    	now  =now.truncatedTo(ChronoUnit.HOURS);  // 시(hour)보다 작은 단위를 0으로 만듦
    	System.out.println(now);  // 19:00
    }
}

 

 

예제3

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;

class prac{
    public static void main (String[] args) {
    	LocalDate today = LocalDate.now();
    	LocalTime now = LocalTime.now();
    	
    	LocalDate birthDate = LocalDate.of(1999, 12, 31);
    	LocalTime birthTime = LocalTime.of(23, 59, 59);
    	
    	System.out.println(today);  // 2021-11-11
    	System.out.println(now);  // 21:28:54.193
    	System.out.println(birthDate);  // 1999-12-31
    	System.out.println(birthTime);  // 23:59:59
    	
    	System.out.println(birthDate.withYear(2000));  // 2000-12-31
    	System.out.println(birthDate.plusDays(1));  // 2000-01-01
    	System.out.println(birthDate.plus(1, ChronoUnit.DAYS));  // 2000-01-01
    	
    	
    	System.out.println(birthTime.truncatedTo(ChronoUnit.HOURS));  // 23:00
    	
    	System.out.println(ChronoField.CLOCK_HOUR_OF_DAY.range());  // 1 - 24
    	System.out.println(ChronoField.HOUR_OF_DAY.range());  // 0 - 23
 
    }
}

 

 

 

 

Instant 클래스

  • Instant 클래스는 에포크 타임(EPOCH TIME, 1970-01-01 00:00:00 UTC)로부터 경과된 시간을 나노초 단위로 표현
  • 단일 진법(10진법)으로만 다루기 때문에 계산 용이
  • Instant 인스턴스를 생성하려면 now() 메서드 또는 ofEpochSecond() 메서드 이용할 것
  • 특정 시점의 타임스탬프(Time-Stamp)로 사용
  • 주로 특정한 두 시점간의 시간적 우선순위를 따질 때 사용
  • java.util.Date 클래스와 기능 유사. 차이점은 Date 클래스는 로컬 컴퓨터의 현재 날짜와 시간 정보를 기준으로 하지만 Instant 클래스는 협정세계시(1970-01-01 00:00:00 UTC)가 기준 
    • Instant 클래스는 기존의 java.util.Date를 대체하기 위한 것
  • Instant는 항상 UTC(+00:00)를 기준으로 하기 때문에 LocalTime과 차이가 있을 수 있음
    • 한국은 시간대가 UTC 기준 '+09:00' 이므로 Instant와 LocalTime간에 9시간의 시간차가 발생 가능
    • 시간대를 고려하는 경우 OffsetDateTime 클래스를 사용하는것이 더 나을 수도 있음

 

■ Instant 메서드

제어자 반환타입 메서드 설명
static Instant now()
static Instant now(Clock clock)
현재 시간 값을 가진 Instant 인스턴스 생성
static Instant ofEpochSecond(long epochSecond)

static Instant ofEpochSecond(long epochSecond, long nanoAdjustment)
에포크 타임 1970-01-01 00:00:00 UTC 기준으로부터 second초 값이 지난 Instant 인스턴스 생성

long getEpochSecond() 초 단위의 타임스태프값 반환
long toEpochMilli() 밀리초 단위의 타임스태프값 반환
long getnano() 나노초 단위의 타임스태프값 반환

 

■ 인스턴스 상수

제어자 타입 상수 설명
static Instant EPOCH epoch 인스턴스
static Instant MAX '1000000000-12-31T23:59:59.999999999Z' 값을 가진 Instant 인스턴스
static Instant MIN '-1000000000-01-01T00:00Z' 값을 가진  Instant 인스턴스

 

 

 

■ Instant 클래스와 Date 클래스간의 변환

 

Date → Instant  (Date 메서드)

반환타입 메서드 설명
Instant toInsatnt() Date → Instant 변환

 

Instant → Date (Date 메서드)

제어자
반환타입
메서드 설명
static
Date
from(Instant instant) Instant → Date 변환

 

 

 

 

 

◎ LocalDateTime 클래스

  • LocalDate 클래스와 LocalTime 클래스를 합친것
  • of()메서드 또는 now() 메서드를 통해 인스턴스 생성
  • import java.time.LocalDateTime; 쓸 것

 

  LocalDateTime 메서드

제어자
반환타입
접근자 반환타입 메서드 설명
static
LocalDateTime
now() 현재 시간과 날짜 값을 가진 LocalDateTime 인스턴스 생성 
static
LocalDateTime
of(int year, int month, int dayOfMoth, int hour, int minute)

of(int year, int month, int dayOfMonth, int hour, int minute, int second)

of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond)

of(int year, Month month, int dayOfMonth, int hour, int minute)

of(int year, Month month, int dayOfMonth, int hour, int minute, int second)

of(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond)

of(LocalDate date, LocalTime time)
매개변수의 값에 따른 시간와 날짜 값을 가진 LocalDateTime 인스턴스 생성
LocalDate toLocalDate() LocalDate 인스턴스로 변환
LocalTime toLocalTime() LocalTime 인스턴스로 변환
ZoneDateTime atZone(ZoneId zone) 매개변수인 zone 시간대를 합친 ZoneDateTime 인스턴스 생성
LocalDateTime with(TemporalAdjuster adjuster)

with(TemporalField field, long newValue)
① adjuster값으로 바뀐 시간과 날짜값을 가진 ZonedDateTime 인스턴스 생성

② field값이 newValue값으로 바뀐 ZonedDateTime 인스턴스 생성
String format(DateTimeFormatter formatter) 지정된 형식에 맞게 문자열로 반환
static
LocalDateTime
parse(CharSequence text)

parse
(CharSequence text, DateTimeFormatter formatter)
문자열을 파싱하여 LocalDateTime 인스턴스 생성
"yyyy-MM-ddTHH:mm:ss" 양식으로 넣을것
ex) "2015-07-01T17:15:23"

formatter 양식의 문자열을 파싱하여 LocalDateTime 인스턴스 생성

 

 

예제1

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

class prac{
    public static void main (String[] args) {
    	LocalDateTime dateTime = LocalDateTime.of(2015, 11 , 12, 5, 24, 36);
    	LocalDateTime today = LocalDateTime.now();
    	System.out.println(dateTime);  // 2015-11-12T05:24:36
    	System.out.println(today);  // 2021-11-12T12:10:50.992
    	
    	LocalDate date = LocalDate.of(2021,11, 12);
    	LocalTime time = LocalTime.of(12,34 ,56);
    	
    	LocalDateTime dt = LocalDateTime.of(date, time);
    	LocalDateTime dt2 = date.atTime(time);
    	LocalDateTime dt3 = date.atTime(16, 50, 30);
    	LocalDateTime dt4 = date.atStartOfDay();
    	LocalDateTime dt5 = time.atDate(date);
    	LocalDateTime dt6 = time.atDate(LocalDate.of(2015, 12, 31));
    	
    	System.out.println(dt);  // 2021-11-12T12:34:56
    	System.out.println(dt2);  // 2021-11-12T12:34:56
    	System.out.println(dt3);  // 2021-11-12T16:50:30
    	System.out.println(dt4);  // 2021-11-12T00:00
    	System.out.println(dt5);  // 2021-11-12T12:34:56
    	System.out.println(dt6);  // 2015-12-31T12:34:56
    	
    }
}

여러 방법의 LocalDateTime 인스턴스 생성 

 

 

예제2

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.LocalDate;

class prac{
    public static void main (String[] args) {
    	LocalDateTime dt = LocalDateTime.of(2021,10,15, 12,34,55);
    	LocalDate date = dt.toLocalDate();
    	LocalTime time = dt.toLocalTime();
    	
    	System.out.println(dt);  // 2021-10-15T12:34:55
    	System.out.println(date);  // 2021-10-15
    	System.out.println(time);  // 12:34:55
    	
    }
}

LocalDateTime을 LocalDate 또는 LocalTime으로 변환

 

 

 

 

◎ ZonedDateTime

  • LocalDateTime 클래스와 시간대(time-zone)를 합친 클래스
  • import java.time.ZonedDateTime; 쓸 것
  • 기존에는 TimeZone 클래스로 시간대를 다뤘지만 새로운 시간 패키지에서는 ZoneId 클래스를 사용
  • LocalDateTime클래스에 atZone() 메서드를 사용해서 시간대 정보를 추가하여 ZonedDateTime 인스턴스를 얻을 수 있음
  • GregorianCalendar 클래스와 유사

 

 

■ ZonedDateTime 메서드

제어자
반환타입
메서드 설명
static
ZonedDateTime
now()

now(ZoneId zone)

now(Clock clock)
기본시간대와 현재날짜와 시간값을 가진 ZonedDateTime 인스턴스 생성

매개변수인 zone값의 시간대를 가진 현재 시간와 날짜값을 가진ZonedDateTime 인스턴스 생성

기본 시간대와 매개변수인 clock을 값을 가진 ZonedDateTime 인스턴스 생성 
static
ZonedDateTime
of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond, ZoneId zone)

of(LocalDate date, LocalTime time, ZoneId zone)

of(LocalDateTime localDateTime, ZoneId zone)
매개변수 값을 가진 ZonedDateTime 인스턴스 생성
ZoneDateTime withZoneSameInstant(ZoneId zone) 시간과 날짜값은 유지한채 매개변수인 zone 시간대값을 가진 ZonedDateTime 인스턴스 반환
ZoneOffset getOffset() UTC로부터 몇 초만큼 차이가 나는지 그 차이값을 갖는  ZoneOffSet 인스턴스 생성
OffsetDateTime toOffsetDateTime() 시간과 날짜를 OffsetDateTime 인스턴스로 변환후 생성
LocalDate toLocalDate() ZonedDateTime → LocalDate 변환
LocalTime toLocalTime() ZonedDateTime → LocalTime 변환
LocalDateTime toLocalDateTime() ZonedDateTime → LocalDateTime 변환
OffsetDateTime toOffsetDateTime() ZonedDateTime → OffsetDateTime 변환
long toEpochSecond() epoch시간 기준으로 날짜와 시간을 초 단위로 변환
Instant toInstant() ZonedDateTime → Instant 변환
ZoneId getZone() 시간대 값을 가져옴
ex) 'Asia/Seoul' , 'Europe/Paris' 
ZonedDateTime with(TemporalAdjuster adjuster)

 with(TemporalField field, long newValue)
adjuster값으로 바뀐 시간과 날짜값을 가진 ZonedDateTime 인스턴스 생성

② field값이 newValue값으로 바뀐 ZonedDateTime 인스턴스 생성

static
ZonedDateTime
parse(CharSequence text)

parse(CharSequence text, DateTimeFormatter formatter)
문자열을 파싱하여 ZonedDateTime 인스턴스 생성
"yyyy-MM-ddTHH:mm:ss+UTC[ZoneId]"
ex) "2015-10-11T12:34:56+09:00[Asia/Seoul]"
ex) "2017-11-12T01:25:58+01:00[Europe/Paris]"

formatter 양식에 맞게 ZonedDateTime 인스턴스 생성
String format(DateTimeFormat formatter) formatter 양식에 맞게 문자열로 생성
  • toEpochSecond() 메서드와 toInstant() 메서드는 ChronoZonedDateTime 인터페이스에서 상속 받은 것

 

 

■ GregorianCalendar 클래스 메서드

제어자
반환타입
메서드 설명
static
GregorianCalendar
from(ZonedDateTime zdt) ZonedDateTime → GregorianCalendar 변환
ZonedDateTime toZonedDateTime() GregorianCalendar → ZonedDateTime 변환
  • GregorianCalendar클래스 와 ZonedDateTime 클래스 변환 방법

 

◎ ZoneId 클래스

  • ZoneId 클래스는 일광 절약시간(DST, Daylight Saving Time)을 자동적으로 처리해주므로 편함
  • ZoneId 클래스 사용시 import java.timeZoneId; 쓸 것
  • 사용가능한 ZoneId의 목록은 ZoneId.getAvailableZoneIds()로 얻을 수 있음

 

■ ZoneId 메서드

제어자
반환타입
메서드 설명
static
ZoneId
of(String zoneId) zodeid값을 가진 ZoneId인스턴스 생성
abstract
String
getId() 시간대 값을 문자열로 변환

 

 

예제1

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

class prac{
    public static void main (String[] args) {
    	LocalDateTime dateTime = LocalDateTime.now();
    	ZoneId zid = ZoneId.of("Asia/Seoul"); 
    	System.out.println(zid);  // Asia/Seoul
    	
    	ZonedDateTime zdt = dateTime.atZone(zid);
    	System.out.println(zdt);  // 2021-11-12T12:30:16.137+09:00[Asia/Seoul]
    	
    }
}

LocalDateTime 클래스에 ZoneId 클래스를 합쳐 ZonedDateTime 클래스 인스턴스 생성

 

 

예제2

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;

class prac{
    public static void main (String[] args) {
    	ZoneId zid = ZoneId.of("Asia/Seoul");
    	System.out.println(zid);  // Asia/Seoul
    	
    	ZonedDateTime zdt = LocalDate.now().atStartOfDay(zid);
    	System.out.println(zdt);  // 2021-11-12T00:00+09:00[Asia/Seoul]
    	
    }
}

LocalDate 인스턴스의 atStartOfDay(ZoneId zone) 메서드를 이용하여 ZonedDateTime 인스턴스 생성 

 

 

예제3

import java.time.ZoneId;
import java.time.ZonedDateTime;

class prac{
    public static void main (String[] args) {
    	ZoneId nyId = ZoneId.of("America/New_York");
    	ZonedDateTime nyTime = ZonedDateTime.now().withZoneSameInstant(nyId);
    	
    	System.out.println(nyId);    // America/New_York
    	System.out.println(nyTime);  // 2021-11-12T02:58:49.199-05:00[America/New_York]
    }
}

현재 날짜의 현재 시간에 특정 시간대를 구함

 

 

◎ ZoneOffset 클래스

  • UTC로부터 얼마만큼 떨어져있는지를 ZoneOffSet 클래스로으로 표현
  • 서울은 +9 (UTC보다 9시간 빠름, 9시간 = 32400초) 
  • import java.time.ZoneOffset; 쓸 것
  • ZoneId는 일광절약시간처럼 시간대와 관련된 규칙들을 포함하고 있는데 ZoneOffset은 단지 시간대를 시간의 차이로만 구분

 

 

■ ZoneOffset 메서드

제어자
반환타입
메서드 설명
int get(TemporalField field) offset 인스턴스에 저장된 field값을 가져옴

 

 

 

예제1

import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoField;

class prac{
    public static void main (String[] args) {
    	ZoneOffset krOffset = ZonedDateTime.now().getOffset();
    	System.out.println(krOffset);  // +09:00
    	
    	ZoneOffset krOffset2 = ZoneOffset.of("+9");
    	System.out.println(krOffset2);  // +09:00
    	
    	int krOffsetInsec = krOffset.get(ChronoField.OFFSET_SECONDS);
    	System.out.println(krOffsetInsec);  // 32400
    	
    }
}

ZonedDateTime.now().getOffset() 이랑 ZoneOffset.of("+9") 와 기능이 동일

 

 

◎ OffsetDateTime 클래스

  • OffsetDateTime 클래스는 ZoneOffset으로 시간대 표현
  • 서로 다른 시간대의 컴퓨터간의 통신에 유용
  • ZonedDateTime은 ZoneId로 구역을 표현하는데 OffsetDateTime 클래스는 ZoneId가 아닌 ZoneOffset을 사용
  • 같은 지역내의 컴퓨터간에 데이터를 주고 받을 때, 전송시간을 표현하기에 LocalDateTime이면 충분하지만, 서로 다른 시간대에 존재하는 컴퓨터간의 통신에는 OffsetDateTime이 필요
  • OffsetDateTime 클래스는 ZonedDateTime처럼, LocalDate와 LocalTime에 ZoneOffset을 더하거나, ZonedDateTime에 toOffsetDateTime()을 호출해서 얻을 수 있음 

 

 

■ OffsetDateTime 메서드

제어자
반환타입
메서드 설명
static
OffsetDateTime
of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond, ZoneOffset offset)

of(LocalDate date, LocalTime time, ZoneOffset offset)

of(LocalDate date, LocalTime time, ZoneId zone)
매개변수의 값을 가진 OffsetDateTime 인스턴스 생성  

 

 

 

예제1

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

class prac{
    public static void main (String[] args) {
    	LocalDate date = LocalDate.now();
    	LocalTime time = LocalTime.now();
    	ZoneId zid = ZoneId.of("Asia/Seoul");
    	
    	ZonedDateTime zdt = ZonedDateTime.of(date, time, zid);
    	System.out.println(zdt);
    	
    	OffsetDateTime odt = zdt.toOffsetDateTime();
    	System.out.println(odt);
    }
}

ZonedDateTime 클래스의 toOffsetDateTime() 메서드를 통해 OffsetDateTime 인스턴스 생성

 

 

 

 

 

예제2

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

class prac{
    public static void main (String[] args) {
    	LocalDate date = LocalDate.of(2021, 11, 12);
    	LocalTime time = LocalTime.of(19, 13);
    	LocalDateTime dt = LocalDateTime.of(date, time);
    	ZoneId zid = ZoneId.of("Asia/Seoul");
    	ZonedDateTime zdt = dt.atZone(zid);
    	
    	// 시간대를 문자열로 변환
    	String strZid = zdt.getZone().getId();
    	ZoneId zi = zdt.getZone();
    	
    	
    	ZonedDateTime seoulTime = ZonedDateTime.now();
    	ZoneId nyId = ZoneId.of("America/New_York");

    	// 시간대를 nyId 값으로 변경
    	ZonedDateTime nyTime = ZonedDateTime.now().withZoneSameInstant(nyId);
    	
    	// ZonedDateTime → OffsetDateTime 변환
    	OffsetDateTime odt = zdt.toOffsetDateTime();
    	
    	
    	System.out.println(zi);          // Asia/Seoul
    	System.out.println(strZid);      // Asia/Seoul
    	System.out.println(dt);         // 2021-11-12T19:13
    	System.out.println(zid);        // Asia/Seoul
    	System.out.println(nyTime);     // 2021-11-12T05:28:33.478-05:00[America/New_York]
    	System.out.println(zdt);        // 2021-11-12T19:13+09:00[Asia/Seoul]
    	System.out.println(odt);        // 2021-11-12T19:13+09:00
    	
    }
}

 

 

 

 

 

◎ TemporalAdjusters 클래스

  • 날짜 계산 메서드를 정의해놓은 것
  • plus(), minus() 메서드로 날짜를 계산하기엔 복잡하기에 TemporalAdjusters 클래스를 사용할 것
  • import TemporalAdjusters; 쓸 것

 

■ TemporalAdjusters 메서드

제어자
반환타입
메서드 설명
static
TemporalAdjuster
firstDayOfNextYear() 다음 해의 첫 날
static
TemporalAdjuster
firstDayOfNextMonth() 다음달의 첫 날
static
TemporalAdjuster
firstDayOfYear() 올 해의 첫 날
static
TemporalAdjuster
firstDayOfMonth() 이번 달의 첫 날
static
TemporalAdjuster
lastDayOfYear() 올해의 마지막 날
static
TemporalAdjuster
lastDayOfMonth() 이번 달의 마지막 날
static
TemporalAdjuster
firstInMonth(DayOfWeek dayOfWeek) 이번 달의 첫 번째 ? 요일
static
TemporalAdjuster
lastInMonth(DayOfWeek dayOfWeek) 이번 달의 마지막 ?요일
static
TemporalAdjuster
previous(DayOfWeek dayOfWeek) 지난 ?요일 (당일 미포함)
static
TemporalAdjuster
previousOrSame(DayOfWeek dayOfWeek) 지난 ?요일(당일 포함)
static
TemporalAdjuster
next(DayOfWeek dayOfWeek) 다음 ?요일 (당일 미포함)
static
TemporalAdjuster
nextOfSame(DayOfWeek dayOfWeek) 다음 ?요일 (당일 포함)
static
TemporalAdjuster
dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek) 이번 달의 n번째 ?요일

 

 

 

 

◎ TemporalAdjuster 인터페이스 구현

public interface TemporalAdjuster {
    Temporal adjustInto(Temporal temporal);
}
  • 필요시 날짜 계산 메서드를 만들 수 있음
  • 메서드 작성시 매개변수를 TemporalAdjuster인터페이스를 구현한 클래스의 객체로 설정할 것
  • TemporalAdjuster 인터페이스를 구현한 클래스의 객체를 매개변수로 제공해야함
  • TemporalAdjuster인터페이스 구현히 adjustInto() 메서드 구현할 것
  • 날짜와 시간에 관련된 대부분의 클래스는 Temporal인터페이스를 구현한것이므로 adjustInto()의 매개변수가 될 수 있음
  • adjustInto()메서드만 구현하고 사용할때는 with() 메서드의 매개변수로 사용할 것
  • import java.time.temporal.TemporalAdjuster; , import java.time.temporal.Temporal;  쓸 것

 

 

◎ DayOfWeek 클래스

  • import java.time.DayOfWeek; 쓸 것

 

■ DayOfWeek 상수값

상수 설명
MONDAY 월요일
TUESDAY 화요일
WEDNESDAY 수요일
THURSDAY 목요일
FRIDAY 금요일
SATURDAY 토요일
SUNDAY 일요일

 

 

예제1

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;

class DayAfterTomorrow implements TemporalAdjuster{  // 특정 날짜로부터 2일후의 날짜를 계산
	@Override
	public Temporal adjustInto(Temporal temporal) {
		return temporal.plus(2, ChronoUnit.DAYS);
	}
}

class prac{
    public static void main (String[] args) {
    	LocalDate today = LocalDate.now();
    	LocalDate date = today.with(new DayAfterTomorrow());  // TemporalAdjuster를 구현한 메서드를 with()의 매개변수로 사용할 것
    	
    	p(today);
    	p(date);
    	
    	p(today.with(TemporalAdjusters.firstDayOfNextMonth()));   // 다음 달의 첫 날
    	p(today.with(TemporalAdjusters.firstDayOfMonth()));  // 이달의 첫 날
    	p(today.with(TemporalAdjusters.lastDayOfMonth()));  // 이 달의 마지막 날
    	p(today.with(TemporalAdjusters.firstInMonth(DayOfWeek.TUESDAY)));  // 이 달의 첫번째 화요일
    	p(today.with(TemporalAdjusters.lastInMonth(DayOfWeek.TUESDAY)));  // 이 달의 마지막 화요일
    	p(today.with(TemporalAdjusters.previous(DayOfWeek.TUESDAY)));  // 지난 주 화요일
    	p(today.with(TemporalAdjusters.previousOrSame(DayOfWeek.TUESDAY)));  // 지난 주 화요일 (오늘 포함)
    	p(today.with(TemporalAdjusters.next(DayOfWeek.TUESDAY)));  // 다음 주 화요일
    	p(today.with(TemporalAdjusters.nextOrSame(DayOfWeek.TUESDAY)));  // 다음 주 화요일 (오늘 포함)
    	p(today.with(TemporalAdjusters.dayOfWeekInMonth(4, DayOfWeek.TUESDAY)));  // 이 달의 4번째 화요일
    	
    }
    static void p(Object obj) {  //라인의 길이를 줄이기 위한 새로 정의한 메서드
    	System.out.println(obj);
    }
    
}

/* 출력값
2021-11-12
2021-11-14
2021-12-01
2021-11-01
2021-11-30
2021-11-02
2021-11-30
2021-11-09
2021-11-09
2021-11-16
2021-11-16
2021-11-23
*/

 

 

 

 

◎ Period 클래스

  • 날짜의 차이를 계산하기 위한 클래스
  • import java.time.Period; 쓸 것

 

■ Period 메서드

제어자
반환타입
메서드 설명
static
Period
between(LocalDate startDateInclusive, LocalDate endDateExclusive) 두 날짜의 차이 값을 가진 Period 인스턴스 생성
long get(TemporalUnit unit) unit 값 반환
int getDays()
int getMonths()
int getYears()
List<temporalUnit> getUnits() 해당 Period인스턴스가 가지고 있는 필드들을 리스트 형태로 반환 
static
Period
of(int years, int months, int days) 해당 매개변수를 갖는 Period 인스턴스 생성
static
Period
ofDays(int days) 해당 매개변수를 갖는 Period 인스턴스 생성
static
Period
ofMonths(int months) 해당 매개변수를 갖는 Period 인스턴스 생성
static
Period
ofYears(int years) 해당 매개변수를 갖는 Period 인스턴스 생성
static
Period
ofWeeks(int weeks) 해당 매개변수를 갖는 Period 인스턴스 생성
Period withDays(int days) 해당 매개변수 값을 바꾼 Period 인스턴스 생성
Period withMonths(int months) 해당 매개변수 값을 바꾼 Period 인스턴스 생성
Period withYears(int years) 해당 매개변수 값을 바꾼 Period 인스턴스 생성
Period plus(TemporalAmount amountToAdd) 매개변수 값을 추가한 Period인스턴스 생성
Period plusDays(long daysToAdd) 매개변수 값을 추가한 Period인스턴스 생성
Period plusMonths(long monthsToAdd) 매개변수 값을 추가한 Period인스턴스 생성
Period plusYears(long yearsToAdd) 매개변수 값을 추가한 Period인스턴스 생성
Period multipliedBy(int scalar) 날짜를 곱함
boolean isZero() 0인지 아닌지 판단
0이면 true
boolean isNegative() 음수면 true
Period normalized() 월(month) 값을 12를 넘기 않게 바꿈. 12를 넘어갈 경우 년 값을 올림.
일(day) 값은 일정하지 않기 때문에 그대로 놔둠
ex) 1년 13개월 → 2년 1개월
long toTotalMonths() 년월일을 월 단위로 변환해서 반환
(일 단위는 무시)
  • Period클래스의 between() 메서드와 LocalDate클래스의 until()메서드는 같은 기능을 가짐. 단, between()은 static 메서드며 until()은 인스턴스 메서드라는 차이를 가짐
  • Period 클래스는 년월일을 분리해서 저장하기 때문에 D-day를 구하려면 두 개의 매개변수를 받는 until(Temporal endExclusive, TemporalUnit unit) 을 사용할 것

 

 

예제1

import java.time.LocalDate;
import java.time.Period;

class prac{
    public static void main (String[] args) {
    	LocalDate date1 = LocalDate.of(2014,1, 1);
    	LocalDate date2 = LocalDate.of(2015, 12, 31);
    	
    	Period pe = Period.between(date1, date2);
    	System.out.println(pe);  // P1Y11M30D
    	
    	System.out.println(pe.getUnits());  // [Years, Months, Days]
    }
}

between() 메서드를 통해 날짜차 구하기

 

 

 

 

◎ Duration 클래스

  • 시간 차이 계산하기 위한 클래스
  • import java.time.Duration; 쓸 것
  • Duration 클래스의 메서드는 Chrono.SECONDS 와 Chrono.NANOS 타입만 반환 받을 수 있음. 시, 분, 초 값으로는 반환 받을 수 없음
  • 그래서 Duration을 LocalTime으로 변환한 다음에 LocalTime의 메서드인 getHour(), getMinute(), getSecond(), getNano() 메서드를 통해서 여러 타입의 반환 값을 얻어올 것 

 

■ Duration 메서드

제어자
반환타입
메서드 설명
static
Duration
between(Temporal startInclusive, Temporal endExclusive) 두 날짜의 차이 값을 가진 Period 인스턴스 생성
long get(TemporalUnit unit) unit 값 반환
long getSeconds()
int getNano() 나노 초
List<TemporalUnit> getUnits() 해당 Duration인스턴스가 가지고 있는 필드들을 리스트 형태로 반환 
static
Duration
of(long amount, TemporalUnit unit) 해당 매개변수를 갖는 Period 인스턴스 생성
static
Duration
ofDays(long days) 해당 매개변수를 갖는 Period 인스턴스 생성
static
Duration
ofHours(long hours) 해당 매개변수를 갖는 Period 인스턴스 생성
static
Duration
ofMinutes(long minutes) 해당 매개변수를 갖는 Period 인스턴스 생성
static
Duration
ofSeconds(long seconds)

ofSeconds
(long seconds, long nanoAdjustment)
해당 매개변수를 갖는 Period 인스턴스 생성
static
Duration
ofNanos(long minutes) 해당 매개변수를 갖는 Period 인스턴스 생성
static
Duration
ofMillis(long millis) 해당 매개변수를 갖는 Period 인스턴스 생성
Duration plus(Duration duration)

plus
(long amountToAdd, TemporalUnit unit)
매개변수 값을 추가한 Duration인스턴스 생성
Duration plusDays(long daysToAdd) 매개변수 값을 추가한 Duration인스턴스 생성
Duration plusHours(long hoursToAdd) 매개변수 값을 추가한 Duration인스턴스 생성
Duration plusMinutes(long minutesToAdd) 매개변수 값을 추가한 Duration인스턴스 생성
Duration plusSeconds(long secondsToAdd) 매개변수 값을 추가한 Duration인스턴스 생성
Duration plusNanos(long nanosToAdd) 매개변수 값을 추가한 Duration인스턴스 생성
Duration plusMillis(long millisToAdd) 매개변수 값을 추가한 Duration인스턴스 생성
Duration plus(Duration duration)

plus(long amountToAdd, TemporalUnit unit)
매개변수 값을 뺀 Duration인스턴스 생성
Duration minusDays(long daysToSubtract) 매개변수 값을 뺀 Duration인스턴스 생성
Duration minusHours(long hoursToSubtract) 매개변수 값을 뺀 Duration인스턴스 생성
Duration minusMinutes(long minutesToSubtract) 매개변수 값을 뺀 Duration인스턴스 생성
Duration minusSeconds(long secondsToSubtract) 매개변수 값을 뺀 Duration인스턴스 생성
Duration minusNanos(long nanosToSubtract) 매개변수 값을 뺀 Duration인스턴스 생성
Duration minusMillis(long millisToSubtract) 매개변수 값을 뺀 Duration인스턴스 생성
Duration multipliedBy(long multiplicand) 시간을 곱한 값을 가진 Duration 인스턴스 생성
Duration divideBy(long divisior) 시간을 나눈 값을 가진 Duration 인스턴스 생성
boolean isZero() 값이 0이면 true
boolean isNegative() 시간차이가 음수면 true
Duration negated() 부호를 반대로 바꿈
음수 → 양수
양수 → 음수
Duration abs() 시간차이 값을 양수로 바꿈
long toDays() 일 단위로 변환
long toHours() 시간 단위로 변환
long toMinutes() 분 단위로 변환
long toNanos() 나노초 단위로 변환
long toMillis() 천분의 일초 단위로 변환

 

 

예제1 

import java.time.Duration;
import java.time.LocalTime;

class prac{
    public static void main (String[] args) {
    	LocalTime time1 = LocalTime.of(00, 00,00);
    	LocalTime time2 = LocalTime.of(12, 34,56);
    	
    	Duration du = Duration.between(time1, time2);
    	System.out.println(du);  // T12H34M56S
    	
    	System.out.println(du.getUnits());  // [Seconds, Nanos]

    }
}

between() 메서드를 통해 시간차 구하기

 

예제2

import java.time.Duration;
import java.time.LocalTime;

class prac{
    public static void main (String[] args) {
    	LocalTime time1 = LocalTime.of(0, 0, 0); 
    	LocalTime time2 = LocalTime.of(12, 34, 56); 
    	Duration du = Duration.between(time1, time2);
    	
    	LocalTime tmpTime = LocalTime.of(0, 0).plusSeconds(du.getSeconds());
    	
    	int hour = tmpTime.getHour();
    	int min = tmpTime.getMinute();
    	int sec = tmpTime.getSecond();
    	int nano = tmpTime.getNano();
    	int nano2 = du.getNano();
    	
    	System.out.println(tmpTime);  // 12:34:56
    	System.out.println(hour);  // 12
    	System.out.println(min);  // 34
    	System.out.println(sec);  // 56
    	System.out.println(nano);  // 0
    	System.out.println(nano2);  // 0
    	
    }
}

시, 분, 초 값을 얻기 위해 Duration을 LocalTime로 변환 후 LocalTime 클래스의 get 메서드들을 사용후 시, 분. 초값을 가져옴 

 

 

예제3

import java.time.LocalDate;
import java.time.Period;
import java.time.temporal.ChronoUnit;

class prac{
    public static void main (String[] args) {
    	LocalDate day1 = LocalDate.of(2021, 11, 10);
    	LocalDate day2 = LocalDate.of(2021, 11, 13);
    	
    	Period pe = Period.between(day1, day2);
    
    	Period pe2 = day1.until(day2);
    	long d_day = day1.until(day2, ChronoUnit.DAYS);
    	
    	
    	System.out.println(pe);   // P3D
    	System.out.println(pe2);  // P3D
    	System.out.println(d_day);  // 3
    	
    	
    }
}

Period 클래스의 between() 메서드는 static 메서드이지만 LocalDate클래스의 until()메서드는 인스턴스 메서드

Period클래스는 년월일을 분리해서 저장하기 때문에 D-day를 구하려는 경우에는 두 개의 매개변수를 받는 until(Temporal endExclusive, TemporalUnit unit) 사용할 것

 

 

예제4

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;

class prac{
    public static void main (String[] args) {

    	Period pe = Period.of(1, 12, 31);
    	
    	Duration du = Duration.of(60, ChronoUnit.SECONDS);
    	Duration du2 = Duration.ofSeconds(60);
    	
    	System.out.println(pe);   // P1Y12M31D
    	System.out.println(du);   // PT1M 
    	System.out.println(du2);   // PT1M
    	
    	
    	// with() 함수로 필드값 변경
    	pe = pe.withYears(2);   // 1년 → 2년
    	du = du.withSeconds(120);  // 60초 → 120초
    	
    	System.out.println(pe);   // P2Y12M31D
    	System.out.println(du);  // PT2M
    	
    	
    	// 사칙연산
    	pe = pe.minusYears(1).multipliedBy(2);  // 1년 빼고 2년 곱함
    	du = du.plusHours(1).dividedBy(60);   // 1시간 더하고 60으로 나눔
    	
    	System.out.println(pe);   // P2Y24M62D
    	System.out.println(du);   // PT1M2S
    	
    	
    	// 비교연산
    	LocalDate date1 = LocalDate.of(2021, 10, 1);
    	LocalDate date2 = LocalDate.of(2021, 10, 1);
    	
    	LocalTime time1 = LocalTime.of(15, 15);
    	LocalTime time2 = LocalTime.of(17, 25);
    	
    	
    	boolean sameDate = Period.between(date1, date2).isZero();
    	boolean isBefore = Duration.between(time1, time2).isNegative();  // 음수일 경우 true
    	
    	System.out.println(sameDate);   // true
    	System.out.println(isBefore);  // false
    	
    	
    	// 부호 바꾸기
    	Duration du3 = Duration.ofDays(-5);
    	System.out.println(du3);  // PT-120H
    	
    	if(du3.isNegative()) {  // du3 값이 음수일경우
    		du3 = du3.negated();  // 부호변경  양수 → 음수   ,  음수 → 양수
    		System.out.println(du3);  // PT120H
    	}
    	
    	du3 = du3.abs();  // 부호를 무조건 양수로 바꿈 
    	System.out.println(du3);   // PT120H
    	
    	
    	Period pe2 = Period.ofDays(-4);
    	System.out.println(pe2);  // P-4D
    	
    	if(pe2.isNegative()) {   // 값이 음수일경우
    		pe2 = pe2.negated();  // 부호를 바꿈   양수 → 음수   ,  음수 → 양수
    	}
    	
    	System.out.println(pe2);  // P4D
    	
    	
    	// normalized()
    	Period pe3 = Period.of(1, 13, 33);
    	System.out.println(pe3);  // P1Y13M33D
    	
    	pe3 = pe3.normalized();
    	System.out.println(pe3);  // P2Y1M33D
    	
    }
}

Period클래스는 abs() 메서드가 없음

normalized()메서드는 월(month) 값을12를 넘지 않게 년도(year) 값을 올려서 값을 바꿔주지만 일(day)값을 달마다 바뀌기 때문에 일(day)값은 변경하지 않음

 

 

 

 

예제5

import java.time.LocalDate;
import java.time.LocalTime;

class prac{
    public static void main (String[] args) {

    	LocalDate date1 = LocalDate.of(2015, 11, 28);
    	LocalDate date2 = LocalDate.of(2015, 11, 29);
    	
    	long period = date2.toEpochDay() - date1.toEpochDay();
    	System.out.println(period);  // 1
    		
    	
    	LocalTime time1 = LocalTime.of(10, 50);
    	LocalTime time2 = LocalTime.of(11, 50);
    	
    	int duration = time1.toSecondOfDay() - time2.toSecondOfDay();
    	System.out.println(duration);  // -3600
    	
    	long duration2 = time1.toNanoOfDay() - time2.toNanoOfDay();
    	 System.out.println(duration2);  // -3600000000000
    	 
    }
}

Period 클래스와 Duration 클래스 없이 시간차, 날짜차이 구하기

 

 

예제6

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;

class prac{
    public static void main (String[] args) {
    	LocalDate date1 = LocalDate.of(2014, 1, 1);
    	LocalDate date2 = LocalDate.of(2015, 12, 31);
    	
    	Period pe = Period.between(date1, date2);
    	
    	System.out.println(date1);  // 2014-01-01
    	System.out.println(date2);  // 2015-12-31
    	System.out.println(pe);   // P1Y11M30D
    	
    	System.out.println(pe.get(ChronoUnit.YEARS));  // 1
    	System.out.println(pe.get(ChronoUnit.MONTHS));  // 11
    	System.out.println(pe.get(ChronoUnit.DAYS));  // 30
    	
    	LocalTime time1 = LocalTime.of(0, 0, 0);
    	LocalTime time2 = LocalTime.of(12, 34, 56);
    	
    	Duration du = Duration.between(time1, time2);
    	
    	System.out.println(time1);  // 00:00
    	System.out.println(time2);  // 12:34:56
    	System.out.println(du);  // PT12H34M56S
    	
    	LocalTime tmpTime = LocalTime.of(0, 0).plusSeconds(du.getSeconds());
    	
    	System.out.println(tmpTime.getHour());  // 12
    	System.out.println(tmpTime.getMinute());  // 34
    	System.out.println(tmpTime.getSecond());  // 56
    	System.out.println(tmpTime.getNano());  // 0
    	
    	 
    }
}

 

 

 

 

 

◎ 파싱과 포맷

  • 형식화(formatting)와 관련된 클래스들은 java.time.format 패키지에 있음. 그 중 DateTimeFormatter 클래스가 핵심
  • java.time.format 패키지 없이 LocalTime, LocalDate, LocalDateTime 클래스의 format() 메서드로도 파싱 가능
  • 파싱(parsing) = 문자열 → 날짜와 시간을 생성
    • 문자열을 날짜 또는 시간으로 변환하려면 static 메서드인 parse() 메서드를 사용할 것
    • 날짜와 시간을 표현하는데 사용되는 클래스들은 거의 다 parse() 메서드를 가지고 있음 
    • DateTimeFormatter 클래스의 ofPattern()메서드를 통해서도 파싱 가능
  • 포맷팅(Formatting) = 날짜와 시간 → 문자열로 변환 

 

예제

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

class prac{
    public static void main (String[] args) {
    	LocalDate date = LocalDate.of(2016, 1, 2);
    	String str1 = DateTimeFormatter.ISO_LOCAL_DATE.format(date);
    	
    	String str2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
    	
    	System.out.println(str1);  // 2016-01-02
    	System.out.println(str2);  // 2016-01-02
    }
}

 

 

 

◎ DateTimeFormatter 클래스

  • 날짜, 시간의 데이터를 지정된 형식에 맞춰 문자열로 반환 
  • format() 메소드를 통해 날짜와 시간을 형식화
  • import java.time.format.DateTimeFormatter; 쓸 것

 

 

 

■ DateTimeFormatter 클래스 상수

  • 반환타입 전부 DateTimeFormatter 

 

 

 

■ DateTimeFormatter 클래스 메서드

제어자
반환타입
메서드 설명
String format(TemporalAccessor temporal) 형식에 맞는 데이터를 문자열로 반환
static
DateTimeFormatter
ofLocalizedDate(FormatStyle dateStyle) 로케일(locale)에 종석적이 포맷터 생성
static
DateTimeFormatter
ofLocalizedTime(FormatStyle timeStyle)
로케일(locale)에 종석적이 포맷터 생성
static
DateTimeFormatter
ofLocalizedDateTime(FormatStyle dateTimeStyle)

ofLocalizedDateTime(FormatStyle dateStyle, FormatStyle timeStyle)
로케일(locale)에 종석적이 포맷터 생성
static
DateTimeFormatter
ofPattern(String pattern)
pattern을 지정하여 원하는 출력형식을 직접 작성

 

 

■ FormatStyle 클래스 상수

  • import java.time.format.FormatStyle; 쓸 것

 

 

예제1

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

class prac{
    public static void main (String[] args) {
    	DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
    	String shortFormat = formatter.format(LocalDate.of(2021, 10, 5));
    	System.out.println(shortFormat);  // 21. 10. 5
    }
}

 

 

 

■ 출력형식 직접 정의

  • DateTimeFormatter 클래스의 ofPattern() 메서드를 통해 출력형식 직접 정의 가능

 

DateTimeFormatter의 패턴에 사용되는 기호

기호 의미 보기
G 연대(BC, AD) 서기 또는 AD
y
u
년도 2015
M
L
월(1~12 또는 1월~12월) 11 또는 11월
Q
q
분기(quarter) 4
w 년의 몇 번째 주 (1~53) 48
W 월의 몇 번째 주 (1~5) 4
D 년의 몇 번째 일 (1~366) 332
d 월의 몇 번째 일 (1~31) 28
F 월의 몇 번째 요일 (1~5) 4
E
e
요일
7
a 오전/오후 (AM/PM) 오후
H 시간 (0~23) 22
h 시간 (1~12) 10
K 시간 (0~11) 10
k 시간 (1~24) 22
m 분 (0~59) 12
s 초 (0~59) 35
S 천분의 일초 (0~999) 7
A 천분의 일초
(그 날의 0시 0분 0초 부터의 시간)
80263808
n 나노초 (0~999999999) 475000000
N 나노초
(그 날의 0시 0분 0초 부터의 시간)
81069992000000
V 시간대 ID (VV) Asia/Seoul
z 시간대 (time-zone) 이름 KST
O 지역화된 zone-offset GMT+9
Z zone-offset +0900
X
x
zone-offset (Z는 +00:00 의미) +09
' escape문자 (특수문자를 표현하는데 사용) 없음

 

 

예제1

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

class prac{
    public static void main (String[] args) {
    	LocalDateTime now = LocalDateTime.now();
    	DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy년 MMM d일 a h시 m분");
    	
    	String nowString = now.format(formatter);
    	System.out.println(nowString);  //2021년 11월 14일 오후 1시 41분
    	
    }
}

ofPattern() 메서드를 이용하여 원하는 출력방식을 포맷팅하여 문자열로 출력

 

 

예제2

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

class prac{
    public static void main (String[] args) {
    	ZonedDateTime zdateTime = ZonedDateTime.now();
    	
    	String[] patternArr = {
    			"yyyy-MM-dd HH:MM:ss",
    			"''yy년 MMM dd일 E요일",
    			"yyyy년 MMM dd일 HH:mm:ss.SSS z VV",
    			"yyyy-MM-dd hh:mm:ss a",
    			"오늘은 올 해의 D번째 날",
    			"오늘은 이 달의 d번째 날",
    			"오늘은 올 해의 w번째 주",
    			"오늘은 이 달의 W번째 주 ",
    			"오늘은 이 달의 w번째 E요일"
    	};
    	
    	for(String p : patternArr) {
    		DateTimeFormatter formatter = DateTimeFormatter.ofPattern(p);  // 원하는 출력 형식 설정
    		System.out.println(zdateTime.format(formatter));
    	}
    	
    }
}
/* 출력값
2021-11-14 14:11:35
'21년 11월 14일 일요일
2021년 11월 14일 14:02:35.651 KST Asia/Seoul
2021-11-14 02:02:35 오후
오늘은 올 해의 318번째 날
오늘은 이 달의 14번째 날
오늘은 올 해의 47번째 주
오늘은 이 달의 3번째 주 
오늘은 이 달의 47번째 일요일
*/

ofPattern() 메서드를 이용하여 원하는 출력방식을 포맷팅하여 문자열로 출력

 

 

예제3

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

class prac{
    public static void main (String[] args) {
    	LocalDate newYear = LocalDate.parse("2016-01-01", DateTimeFormatter.ISO_LOCAL_DATE);  // 날짜 객체 생성
    	
    	LocalDate date = LocalDate.parse("2001-01-01");  // 날짜 객체 생성
    	LocalTime time = LocalTime.parse("23:59:59"); // 시간 객체 생성
    	LocalDateTime dateTime = LocalDateTime.parse("2005-05-05T23:59:59");
    	
    	
    	DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");  // 패턴 생성
    	
    	LocalDateTime endOfYear = LocalDateTime.parse("2015-12-31 23:59:59", pattern);  // 패턴에 맞는 날짜,시간 객체 생성
    	
    	
    	System.out.println(newYear);   // 2016-01-01
    	System.out.println(date);  // 2001-01-01
    	System.out.println(time);  // 23:59:59
    	System.out.println(dateTime);  // 2005-05-05T23:59:59
    	System.out.println(endOfYear);  // 2015-12-31T23:59:59
    }
}

파싱하기

728x90