날짜와 시간 관련 클래스 및 패키지
① 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와 같은 클래스 존재
■ 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
}
}
파싱하기
'[자바] > 자바의 정석 - 3판' 카테고리의 다른 글
Chapter 11 컬렉션 프레임웍(Collections Framewor) (0) | 2021.11.16 |
---|---|
Chapter 09 java.lang 패키지와 유용한 클래스 (0) | 2021.10.30 |
Chapter08 예외처리 (0) | 2021.10.27 |
Chapter07 객체지향2 (0) | 2021.10.17 |
Chapter06. 객체지향 (0) | 2021.09.25 |