1. Time 패키지 들어가기 전
- Java에서 기본적으로 사용했던 날짜와 시간을 다루는 API
- java.util.Date
- java.util.Calendar
- but!! 사용하기 불편하고 여러가지 문제가 많아서 개선된 날짜와 시간 API를 제공
2. Date 와 Calendar 클래스
2-1. Date 클래스는 Deprecated
- 날짜를 가볍게 취급하기 위해 사용되던 클래스.
- 지금은 생성자를 비롯해 대부분의 메소드가 Deprecated 되어있다.
Deprecated 란?
향후 버전이 업데이트 되면서 사라지게 될 기능이니 가급적이면 사용을 권장하지 않는다는 의미.
하지만 하위 버전의 호환성 때문에 한 번에 제거된 것은 아니고 남겨두었기 때문에 사용은 가능.
package com.ohgiraffers.section05.calender;
import java.text.SimpleDateFormat;
public class Application1 {
public static void main(String[] args) {
/* 수업목표. java.util.Date 클래스 사용법을 이해하고 사용할 수 있다. */
java.util.Date today = new java.util.Date(); // 시스템의 현재 시간을 가진 객체 생성 / 풀네임으로 작성
System.out.println("today = " + today);
System.out.println("long 타입 시간: " + today.getTime()); // KST로 1970년 1월 1일 오전 9시 이후 흐름 milliseconds
System.out.println("long 타입 시간을 활용한 Date: " + new java.util.Date(0L));
System.out.println("현재 시간을 활용한 Date: " + new java.util.Date(today.getTime()));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy년 MM월 dd일 HH:mm:ss E요일");
String todayFormat = sdf.format(today);
System.out.println("todayFormat = " + todayFormat);
/* 설명. java.util.Date -> java.sql.Date */
java.util.Date today2 = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(today2.getTime()); // sql.Date형의 생성자 활용
/* 설명. util.Date를 sql.Date로 다운캐스팅을 하기 위해선 실제 객체가 sql.Date형이어야 한다. */
// java.sql.Date sqlDate2 = (java.sql.Date)today2;
// System.out.println(sqlDate2);
/* 설명. java.sql.Date -> java.util.Date */
java.util.Date utilDate = sqlDate; // 다형성 적용
// sql.Date가 util.Date의 자식
}
}
// 실행 결과
today = Sat Jul 20 01:38:23 KST 2024
long 타입 시간: 1721407103070
long 타입 시간을 활용한 Date: Thu Jan 01 09:00:00 KST 1970
현재 시간을 활용한 Date: Sat Jul 20 01:38:23 KST 2024
todayFormat = 2024년 07월 20일 01:38:23 토요일
2-3. Calendar 클래스란?
- Date 클래스보다는 많은 보완이 되었지만, 여전히 다양한 단점 존재.
- Calendar 인스턴스는 불변객체가 아니기 때문에 값을 수정할 수 있다.
- 윤초(leap second)를 고려하지 않는다.
- Calendar 클래스는 월을 나타낼 때 0 부터 11까지로 표현하는 불편함이 있다.
package com.ohgiraffers.section05.calender;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class Application2 {
public static void main(String[] args) {
/* 수업목표. java.util.Calendar 클래스 사용법을 이해하고 사용할 수 있다. */
/* 필기.
* Date형 대비 개선점
* 1. timezone과 관련된 기능이 추가되었다.
* 2. 윤년 관련 기능이 내부적으로 추가되었다.
* 3. 날짜 및 시간 필드 개념을 추가해 불필요한 메소드명을 줄였다.
* */
Calendar calendar = Calendar.getInstance(); // 객체 생성 안된다. static 메소드
System.out.println("calendar = " + calendar);
Calendar calendar2 = new GregorianCalendar();
System.out.println(calendar2.get(Calendar.YEAR));
int year = 1994;
int month = 8 - 1; // 8월
int dayOfMonth = 31;
int hour = 12;
int min = 16;
int second = 0;
Calendar birthDay = new GregorianCalendar(year, month, dayOfMonth, hour, min, second);
System.out.println(birthDay);
System.out.println("태어난 해: " + birthDay.get(1));
System.out.println("태어난 해: " + birthDay.get(Calendar.YEAR));
System.out.println("태어난 월: " + (birthDay.get(Calendar.MONTH)+1)); // 월은 인덱스 구조.
System.out.println("태어난 일: " + birthDay.get(Calendar.DAY_OF_MONTH));
System.out.println("태어난 요일: " + birthDay.get(Calendar.DAY_OF_WEEK));
String day = "";
int dayNum = birthDay.get(Calendar.DAY_OF_WEEK);
switch (dayNum) {
case 1: day = "일"; break;
case 2: day = "월"; break;
case 3: day = "화"; break;
case 4: day = "수"; break;
case 5: day = "목"; break;
case 6: day = "금"; break;
case 7: day = "토"; break;
}
System.out.println("나는 " + day + "요일에 탄생했지");
System.out.println("AM/PM: " + birthDay.get(Calendar.AM_PM)); // 0은 오전, 1이 오후
System.out.println("hourOfDay: " + birthDay.get(Calendar.HOUR_OF_DAY)); // 24시간 체계
System.out.println("hour: " + birthDay.get(Calendar.HOUR)); // 12시간 체계
System.out.println("min: " + birthDay.get(Calendar.MINUTE));
System.out.println("sec: " + birthDay.get(Calendar.SECOND));
/* 설명. SimpleDateFormat 활용(java.util.Date형으로 변환) */
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss E요일");
String birthDayString = sdf.format(new java.util.Date(birthDay.getTimeInMillis()));
System.out.println("birthDayString = " + birthDayString);
}
}
// 실행 결과
calendar = java.util.GregorianCalendar[time=1721407397460,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Seoul",offset=32400000,dstSavings=0,useDaylight=false,transitions=30,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2024,MONTH=6,WEEK_OF_YEAR=29,WEEK_OF_MONTH=3,DAY_OF_MONTH=20,DAY_OF_YEAR=202,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=3,AM_PM=0,HOUR=1,HOUR_OF_DAY=1,MINUTE=43,SECOND=17,MILLISECOND=460,ZONE_OFFSET=32400000,DST_OFFSET=0]
2024
java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Seoul",offset=32400000,dstSavings=0,useDaylight=false,transitions=30,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=?,YEAR=1994,MONTH=7,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=31,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=1,HOUR=0,HOUR_OF_DAY=12,MINUTE=16,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]
태어난 해: 1994
태어난 해: 1994
태어난 월: 8
태어난 일: 31
태어난 요일: 4
나는 수요일에 탄생했지
AM/PM: 1
hourOfDay: 12
hour: 0
min: 16
sec: 0
birthDayString = 1994/08/31 12:16:00 수요일
3. Time 패키지
3-1. Time 패키지
Time 패키지는 4개의 하위 패키지를 가지고 있다.
| 패키지 |
설명 |
| java.time |
날짜와 시간 관련 클래스들을 제공 |
| java.time.chrono |
ISO-8601에 정의된 외에 달력 시스템을 위한 클래스들을 제공 |
| java.time.format |
날짜와 시간 파싱과 형식화 관련 클래스들을 제공 |
| java.time.temporal |
날짜와 시간의 필드와 단위 관련 클래스들을 제공 |
| java.time.zone |
시간대 관련된 클래스들을 제공 |
- 장점
- Date와 Calendar와 다르게 불변하다. 즉 String처럼 날짜와 시간을 변경을 하면 기존의 객체가 변경되는 것이 아닌 새로운 객체가 반환.
- 불편함으로 멀티스레드 환경에서도 안전
3-2. Time 패키지의 핵심 클래스
| 클래스명 |
설명 |
| LocalTime |
시간 관련 작업할 때 사용하는 클래스. LocalTime 객체는 두 개의 정적 메소드를 통해 반환 받을 수 있다. |
| LocalDate |
날짜 관련 작업할 때 사용하는 클래스. LocalDate 객체도 두 개의 정적 메소드로 반환 받는다. |
| LocalDateTime |
시간과 날짤르 함께 작업해야할 때 사용하는 클래스. |
| ZonedDateTime |
시간대(Time Zone)을 활용한 작업해야할 때 사용하는 클래스. |
package com.ohgiraffers.section06.time;
import java.time.*;
public class Application1 {
public static void main(String[] args) {
/* 수업목표. time 패키지에서 제공하는 클래스들의 사용 용법을 이해할 수 있다. */
LocalTime timeNow = LocalTime.now();
LocalTime timeNow2 = LocalTime.of(18, 30, 20);
System.out.println("timeNow = " + timeNow);
System.out.println("timeNow2 = " + timeNow2);
LocalDate dateNow = LocalDate.now();
LocalDate dateOf = LocalDate.of(2024, 7, 19);
System.out.println("dateNow = " + dateNow);
System.out.println("dateOf = " + dateOf);
LocalDateTime dateTimeNow = LocalDateTime.now();
LocalDateTime dateTimeOf = LocalDateTime.of(dateNow, timeNow);
System.out.println("dateTimeNow = " + dateTimeNow);
System.out.println("dateTimeOf = " + dateTimeOf);
ZonedDateTime zonedDateTimeNow = ZonedDateTime.now();
ZonedDateTime zonedDateTimeOf = ZonedDateTime.of(dateOf, timeNow2, ZoneId.of("Asia/Seoul"));
System.out.println("zonedDateTimeNow = " + zonedDateTimeNow);
System.out.println("zonedDateTimeOf = " + zonedDateTimeOf);
}
}
// 실행 결과
timeNow = 01:55:20.223924
timeNow2 = 18:30:20
dateNow = 2024-07-20
dateOf = 2024-07-19
dateTimeNow = 2024-07-20T01:55:20.226591
dateTimeOf = 2024-07-20T01:55:20.223924
zonedDateTimeNow = 2024-07-20T01:55:20.226932+09:00[Asia/Seoul]
zonedDateTimeOf = 2024-07-19T18:30:20+09:00[Asia/Seoul]
package com.ohgiraffers.section06.time;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZonedDateTime;
public class Application2 {
public static void main(String[] args) {
/* 수업목표. time 패키지의 클래스들이 가지고 있는 필드값들을 확인할 수 있다. */
LocalTime localTime = LocalTime.now();
System.out.println("localTime = " + localTime);
System.out.println("시간: " + localTime.getHour());
System.out.println("분: " + localTime.getMinute());
System.out.println("초: " + localTime.getSecond());
System.out.println("나노초: " + localTime.getNano());
LocalDate localDate = LocalDate.now();
System.out.println("localDate = " + localDate);
System.out.println("년: " + localDate.getYear());
System.out.println("월: " + localDate.getMonth());
System.out.println("월 숫자: " + localDate.getMonthValue());
System.out.println("월 중에 몇 번째 일: " + localDate.getDayOfMonth());
System.out.println("1년 중에 몇 번째 일: " + localDate.getDayOfYear());
System.out.println("한 주의 몇 번째 일: " + localDate.getDayOfWeek());
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println("zonedDateTime = " + zonedDateTime);
System.out.println("zone 정보: " + zonedDateTime.getZone());
System.out.println("시차: " + zonedDateTime.getOffset());
}
}
// 실행 결과
localTime = 01:56:05.741056
시간: 1
분: 56
초: 5
나노초: 741056000
localDate = 2024-07-20
년: 2024
월: JULY
월 숫자: 7
월 중에 몇 번째 일: 20
1년 중에 몇 번째 일: 202
한 주의 몇 번째 일: SATURDAY
zonedDateTime = 2024-07-20T01:56:05.747795+09:00[Asia/Seoul]
zone 정보: Asia/Seoul
시차: +09:00
package com.ohgiraffers.section06.time;
import java.time.LocalDateTime;
public class Application3 {
public static void main(String[] args) {
/* 수업목표. time 패키지 클래스를 활용한 덧셈, 뺄셈 및 불변 특성을 이해할 수 있다. */
/* 설명. 불변이므로 새로운 객체가 생성되어 주소값이 바뀜 */ // 불변? 값이 바뀌면 새 객체가 생성.
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("현재 시간: " + localDateTime);
System.out.println("주소값: "+ System.identityHashCode(localDateTime));
LocalDateTime localDateTime2 = localDateTime.plusMinutes(30);
System.out.println("30분 후: " + localDateTime2);
System.out.println("주소값: " + System.identityHashCode(localDateTime2));
LocalDateTime localDateTime3 = localDateTime.minusHours(3);
System.out.println("3시간 전: " + localDateTime3);
System.out.println("주소값: " + System.identityHashCode(localDateTime3));
}
}
// 실행 결과
현재 시간: 2024-07-20T01:57:09.118657
주소값: 2018699554
30분 후: 2024-07-20T02:27:09.118657
주소값: 1118140819
3시간 전: 2024-07-19T22:57:09.118657
주소값: 1975012498
// 주소값 바뀐다.
package com.ohgiraffers.section06.time;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
public class Application4 {
public static void main(String[] args) {
/* 수업목표. time 패키지의 클래스가 제공하는 날짜 비교 연산 메소드를 활용할 수 있다. */
LocalDate localDate = LocalDate.now();
LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime);
LocalDate past = LocalDate.of(2022,11,11);
LocalDateTime future = LocalDateTime.of(2025,1,3,15,20,30);
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
/* 설명. 이전, 이후, 같은 날짜 확인(각 time 패키지 자료형마다 전달이자는 같은 타입이어야 한다.) */
System.out.println(localDate.isAfter(past));
System.out.println(localDateTime.isBefore(future));
System.out.println(zonedDateTime.isEqual(now)); // 왜 false 나오지? -> 나노초까지 구분되기 때문!
}
}
// 실행 결과
2024-07-20T01:57:47.018577+09:00[Asia/Seoul]
2024-07-20T01:57:47.018707+09:00[Asia/Seoul]
true
true
false
package com.ohgiraffers.section06.time;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class Application5 {
public static void main(String[] args) {
/* 수업목표. time 패키지의 클래스들에 포매팅을 적용하여 출력할 수 있다. */
/* 설명. 자동 인식 가능한 패턴일 시 */
String timeNow = "14:05:10";
String dateNow = "2022-10-12";
LocalTime localTime = LocalTime.parse(timeNow);
LocalDate localDate = LocalDate.parse(dateNow);
LocalDateTime localDateTime = LocalDateTime.parse(dateNow + "T" + timeNow);
System.out.println("localTime = " + localTime);
System.out.println("localDate = " + localDate);
System.out.println("localDateTime = " + localDateTime);
/* 설명. 패턴을 인식해 줘야할 시 */
String timeNow2 = "14-05-10";
String dateNow2 = "221005";
LocalTime localTime2 = LocalTime.parse(timeNow2, DateTimeFormatter.ofPattern("HH-mm-ss"));
LocalDate localDate2 = LocalDate.parse(dateNow2, DateTimeFormatter.ofPattern("yyMMdd"));
System.out.println("localTime2 = " + localTime2);
System.out.println("localDate2 = " + localDate2);
/* 설명. time 패키지가 인식한 날짜 및 시간을 원하는 문자열로 반환하기 */
String dateFormat = localDate2.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String timeFormat = localTime2.format(DateTimeFormatter.ofPattern("HH mm"));
System.out.println("dateFormat = " + dateFormat);
System.out.println("timeFormat = " + timeFormat);
}
}
// 실행 결과
localTime = 14:05:10
localDate = 2022-10-12
localDateTime = 2022-10-12T14:05:10
localTime2 = 14:05:10
localDate2 = 2022-10-05
dateFormat = 2022-10-05
timeFormat = 14 05