Java 8에 추가된 LocalDate,LocalTime,LocalDateTime
- 이전 포스팅에 이어 포스팅하겠습니다.
2020/11/02 - [Java/개념] - Java 에서 Date, Calendar클래스가 왜 Deprecated됐는지?
- 이번 포스팅은 java.time 패키지의 LocalDate,LocalTime,LocalDateTime 에 대해 알아보겠습니다.
Java의 Time API 흐름
- Date(jdk 1.0) → Calendar(jdk.1.1) → java.time(jdk 1.8)
LocalDate,LocalTime,LocalDateTime 클래스들의 공통점
- TimeZone 개념을 가지고 있지 않기 때문에 TimeZone에 따라 시간 변환이 불가능합니다.
java.time 패키지
- 이와같이
Date
와Calendar
의 단점을 해소하기위해 JDK 1.8 버전에서java.time
패키지에LocalDateTime
과TimeZone
개념까지 포함할 수 있는ZonedDateTime
이 추가되었다. 따라서 이전보다 안전하고 편하게 날짜를 계산할 수 있다.
LocalDate
LocalDate
클래스는 날짜를 표현하는데 사용된다.- TimeZone 개념이 필요없는 날짜 정보를 나타내기 위해서 사용된다.
LocalDate 사용예제
LocalDate nowDate = LocalDate.now(); //현재 날짜
LocalDate ofDate = LocalDate.of(2020, 11,02); //지정 날짜
LocalDate parseDate = LocalDate.parse("2020-11-02"); //문자열로 날짜 지정
System.out.println(nowDate);
System.out.println(ofDate);
System.out.println(parseDate);
System.out.println("getYear="+parseDate.getYear());
System.out.println("getMonth="+parseDate.getMonth());
System.out.println("getMonthValue="+parseDate.getMonthValue());
System.out.println("getDayOfYear="+parseDate.getDayOfYear());
System.out.println("getDayOfMonth="+parseDate.getDayOfMonth());
System.out.println("getDayOfWeek="+parseDate.getDayOfWeek());
System.out.println("getDayOfMonth="+parseDate.getDayOfMonth());
System.out.println("isLeapYear="+parseDate.isLeapYear());
- 결과
2020-11-02
2020-11-02
2020-11-02
getYear=2020
getMonth=NOVEMBER
getMonthValue=11
getDayOfYear=307
getDayOfMonth=2
getDayOfWeek=MONDAY
getDayOfMonth=2
isLeapYear=true
- 날짜 정보만 찍게 된다. 아래 사용된 메소드를 확인해보자
리턴 타입 |
메소드 및 매개 변수 |
설명 |
int |
getYear() |
해당 날짜 객체의 연도(YEAR) 값을 리턴 |
Month |
getMonth() |
해당 날짜 객체의 월(MONTH_OF_YEAR)의 값을 Enum Month 클래스의 값(JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER) 으로 리턴 |
int |
getMonthValue() |
해당 날짜 객체의 월(MONTH_OF_YEAR) 필드의 값을 리턴함. (1~12) |
int |
getDayOfYear() |
해당 날짜 객체의 일(DAY_OF_YEAR) 필드의 값을 리턴 (1~365, 윤년이면 366) |
int |
getDayOfMonth() |
해당 날짜 객체의 일(DAY_OF_MONTH) 필드의 값을 리턴 (1~31) |
DayOfWeek |
getDayOfWeek() |
해당 날짜 객체의 요일(DAY_OF_WEEK) 필드의 값을 Enum DayOfWeek 클래스의 값 요일(MONDAY, TUESDAY, WEDNESDAY..)로 리턴함 |
boolean |
isLeapYear() |
윤년여부를 리턴 |
LocalTime
LocalTime
클래스는 시간을 표현하는데 사용된다- TimeZone 개념이 필요없는 시간 정보를 나타내기 위해서 사용된다
LocalTime nowTime = LocalTime.now(); //현재 시간
LocalTime ofTime = LocalTime.of(21,30,30); //지정 시간
LocalTime ofNanoTime = LocalTime.of(21,30,30, 30); // 지정 시간(나노초 포함)
LocalTime plusHours = ofTime.plusHours(5);
LocalTime plusMinutes = ofTime.plusMinutes(5);
LocalTime plusSeconds = ofTime.plusSeconds(5);
LocalTime minusHours = ofTime.minusHours(5);
LocalTime minusMinutes = ofTime.minusMinutes(5);
LocalTime minusSeconds = ofTime.minusSeconds(5);
System.out.println(nowTime);
System.out.println(ofTime);
System.out.println(ofNanoTime);
System.out.println("plusHours="+plusHours);
System.out.println("plusMinutes="+plusMinutes);
System.out.println("plusSeconds="+plusSeconds);
System.out.println("minusHours="+minusHours);
System.out.println("minusMinutes="+minusMinutes);
System.out.println("minusSeconds="+minusSeconds);
System.out.println("getHour="+ofTime.getHour());
System.out.println("getMinute="+ofTime.getMinute());
System.out.println("getSecond="+ofTime.getSecond());
System.out.println("getNano="+ofTime.getNano());
- 결과
21:39:17.659400
21:30:30
21:30:30.000000030
plusHours=02:30:30
plusMinutes=21:35:30
plusSeconds=21:30:35
minusHours=16:30:30
minusMinutes=21:25:30
minusSeconds=21:30:25
getHour=21
getMinute=30
getSecond=30
getNano=0
- 시간 정보만 찍게 된다. 아래 사용된 메소드를 확인해보자
리턴 타입 |
메소드 및 매개 변수 |
설명 |
int,long |
get(TemporalField field) |
해당 날짜 객체의 명시된 필드의 값을 int형이나 long형으로 리턴 |
int |
getYear() |
해당 날짜 객체의 연도(YEAR) 필드의 값을 리턴 |
Month |
getMonth() |
해당 날짜 객체의 월(MONTH_OF_YEAR) 필드의 값을 Enum Month 클래스를 이용하여 리턴 |
int |
getMonthValue() |
해당 날짜 객체의 월(MONTH_OF_YEAR) 필드의 값을 리턴. (1~12) |
int |
getDayOfMonth() |
해당 날짜 객체의 일(DAY_OF_MONTH) 필드의 값을 리턴 (1~31) |
int |
getDayOfYear() |
해당 날짜 객체의 일(DAY_OF_YEAR) 필드의 값을 리턴 (1~365, 윤년이면 366) |
DayOfWeek |
getDayOfWeek() |
해당 날짜 객체의 요일(DAY_OF_WEEK) 필드의 값을 Enum DayOfWeek클래스 를 이용하여 리턴 |
int |
getHour() |
해당 시간 객체의 시(HOUR_OF_DAY) 필드의 값을 리턴. |
int |
getMinute() |
해당 시간 객체의 분(MINUTE_OF_HOUR) 필드의 값을 리턴 |
int |
getSecond() |
해당 시간 객체의 초(SECOND_OF_MINUTE) 필드의 값을 리턴 |
int |
getNano() |
해당 시간 객체의 나노초(NANO_OF_SECOND) 필드의 값을 리턴 |
- Calendar 클래스의 단점 이였던 1월을 0으로 표현한것과 요일을 일요일부터 1로 표현했었습니다.
- java.time 패키지에서는 1월을 1로 표현하여 월의 범위가 1
~
12가 되었고 요일은 월요일부터 1로 표현하여서 범위가 1~
7로 변경되었습니다.
LocalDateTime
LocalDateTime
클래스는 날짜와 시간 정보를 모두 표현합니다.
LocalDateTime 예제
LocalDateTime nowDateTime = LocalDateTime.now(); //현재 시간
LocalDateTime nowDateTime2 = LocalDateTime.of(LocalDate.now(), LocalTime.now()); // 현재 날짜와 시간
LocalDateTime paresDateTime = LocalDateTime.parse("2020-11-02T21:59:59.999"); // 문자열 지정된 날짜 시간
LocalDateTime ofDateTime = LocalDateTime.of(2020,11,02,21,59,00); //정수형으로 지정된 날짜 시간
LocalDateTime ofNanoDateTime = LocalDateTime.of(2020,11,02,21,59,00,55); //나노초 포함
LocalDateTime ofDateTime2 = Year.of(2020).atMonth(11).atDay(02).atTime(14, 15); //시간 분
LocalDateTime ofDateTime3 = Year.of(2020).atMonth(11).atDay(02).atTime(14, 15, 50); //시간 분 초
LocalDateTime ofDateTime4 = Year.of(2020).atMonth(11).atDay(02).atTime(14, 15, 50,3); // 시간 분 초 나노초
System.out.println("nowDateTime = " + nowDateTime);
System.out.println("nowDateTime2 = " + nowDateTime2);
System.out.println("paresDateTime = " + paresDateTime);
System.out.println("ofDateTime = " + ofDateTime);
System.out.println("ofNanoDateTime = " + ofNanoDateTime);
System.out.println("ofDateTime2 = " + ofDateTime2);
System.out.println("ofDateTime3 = " + ofDateTime3);
System.out.println("ofDateTime4 = " + ofDateTime4);
System.out.println("getDayOfMonth = " + nowDateTime.getDayOfMonth());
System.out.println("getDayOfWeek = " + nowDateTime.getDayOfWeek());
System.out.println("getDayOfYear = " + nowDateTime.getDayOfYear());
System.out.println("getYear = " + nowDateTime.getYear());
System.out.println("getHour = " + nowDateTime.getHour());
System.out.println("getMinute = " + nowDateTime.getMinute());
System.out.println("getSecond = " + nowDateTime.getSecond());
System.out.println("getNano = " + nowDateTime.getNano());
System.out.println("plusYears = " + nowDateTime.plusYears(1));
System.out.println("plusMonths = " + nowDateTime.plusMonths(1));
System.out.println("plusDays = " + nowDateTime.plusDays(1));
System.out.println("plusHours = " + nowDateTime.plusHours(1));
System.out.println("plusMinutes = " + nowDateTime.plusMinutes(1));
System.out.println("plusSeconds = " + nowDateTime.plusSeconds(1));
- 결과
nowDateTime = 2020-11-02T22:06:02.256149500
nowDateTime2 = 2020-11-02T22:06:02.257147
paresDateTime = 2020-11-02T21:59:59.999
ofDateTime = 2020-11-02T21:59
ofNanoDateTime = 2020-11-02T21:59:00.000000055
ofDateTime2 = 2020-11-02T14:15
ofDateTime3 = 2020-11-02T14:15:50
ofDateTime4 = 2020-11-02T14:15:50.000000003
getDayOfMonth = 2
getDayOfWeek = MONDAY
getDayOfYear = 307
getYear = 2020
getHour = 22
getMinute = 6
getSecond = 2
getNano = 256149500
plusYears = 2021-11-02T22:06:02.256149500
plusMonths = 2020-12-02T22:06:02.256149500
plusDays = 2020-11-03T22:06:02.256149500
plusHours = 2020-11-02T23:06:02.256149500
plusMinutes = 2020-11-02T22:07:02.256149500
plusSeconds = 2020-11-02T22:06:03.256149500
plusNanos = 2020-11-02T22:06:02.256149501
LocalDate
클래스 와LocalTime
클래스의 메소드들이 겹치는 부분이 많기 때문에 메소드는 추론이 가능할 것이다ofDateTime
변수에서 정적 메소드 대신에Year.of()
로 시작하는 것은Fluent API이다. 코드의 가독성이 좋아진다
날짜 비교
LocalDateTime nowDateTime = LocalDateTime.now(); //현재 시간
LocalDateTime nowDateTime2 = LocalDateTime.of(LocalDate.now(), LocalTime.now()); // 현재 날짜와 시간
// nowDateTime 이 nowDateTime2 보다 이전 날짜 인지?
System.out.println(nowDateTime.isBefore(nowDateTime2));
// 동일 날짜 인지?
System.out.println(nowDateTime.isEqual(nowDateTime2));
// nowDateTime 이 nowDateTime2 보다 이후 날짜 인지?
System.out.println(nowDateTime.isAfter(nowDateTime2));
- 결과
false
true
false
- 나노초가 까지 비교하므로 나노초가 있는지 없는지 유무 파악이 중요합니다.
시간 비교
LocalTime nowTime = LocalTime.now(); //현재 시간
LocalTime ofTime = LocalTime.of(21,30,30); //지정 시간
System.out.println(nowTime.isBefore(ofTime));
System.out.println(nowTime.isAfter(ofTime));
- 결과
false
true
날짜와 시간 객체의 비교
- LocalDate와 LocalTime 클래스에도 객체를 비교할 수 있는 compareTo() 메소드가 오버라이딩되어 있습니다.
- 하지만 더욱 편리하게 날짜와 시간 객체를 서로 비교할 수 있도록 다음과 같은 메소드를 제공합니다.
- isEqual() 메소드 : equals() 메소드와는 달리 오직 날짜만을 비교함. (LocalDate 클래스에서만 제공)
- isBefore() 메소드 : 두 개의 날짜와 시간 객체를 비교하여 현재 객체가 명시된 객체보다 앞선 시간인지를 비교함.
- isAfter() 메소드 : 두 개의 날짜와 시간 객체를 비교하여 현재 객체가 명시된 객체보다 늦은 시간인지를 비교함.
- 등등 많은 메소드가 있다
불변(Immutable),Thread-safe
- API를 살펴보면
* This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>
* class; use of identity-sensitive operations (including reference equality
* ({@code ==}), identity hash code, or synchronization) on instances of
* {@code LocalDateTime} may have unpredictable results and should be avoided.
* The {@code equals} method should be used for comparisons.
*
* @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
*/
java.time
패키지들은String
클래스처럼Immutable
하다.- 멀티 쓰레드 환경에서 Thread-safe하다
- 앞 포스팅에서
Calendar
클래스와Date
클래스는mutable
하다고 했었다.- 멀티 쓰레드 환경에서 여러 쓰레드가 동시에 같은 객체에 접근이 가능해서 변경 가능한 객체의 데이터가 변경되어서 잘못된 값을 가질 가능성이 있었다.
'Java > 개념' 카테고리의 다른 글
Java 8 LocalDateTime vs Instant 어떤 상황에서 쓰는게 적합한가? (0) | 2022.08.09 |
---|---|
Java 메모리 최적화가 어떻게 되는지 과정 (0) | 2021.02.25 |
JVM 동적 클래스 로딩 (0) | 2021.02.24 |
[Java] Date, Calendar클래스가 왜 Deprecated됐는지? (0) | 2020.11.02 |
[Java] Date와 Calendar 클래스 (0) | 2020.11.02 |