티스토리 뷰
프로젝트를 진행하면서 시간과 날짜를 계산하는 일이 굉장히 많았다.
하지만 그 과정에서 헷갈린 부분을 정리하고 확실한 개념을 짚고 넘어가보고자 글을 정리한다.
| Date & Time 소개
java8에 새로운 날짜와 시간 API가 생긴 이유
- 그전까지 사용하던 java.util.Date 클래스는 mutable(변하기 쉬운) 하기 때문에 thread safe 하지 않았다.
- 클래스 이름이 명확하지 않다 ( Date인데 시간까지 다루는 점에 대해 의아했음 )
- 버그가 발생하는 일이 많았다 ( type의 안정성이 없고 월 같은 경우 0부터 시작하는게 이해가 안돼..)
- 날짜 시간 처리가 복잡한 application에서는 보통 Joda Time을 쓰곤 했다.
하지만 !!
java8 에서 제공하는 Date-Time API JSR-310 스펙의 구현체를 제공한다.
https://jcp.org/en/jsr/detail?id=310
주요 API
1. 기계용 시간(machine time)과 인류용 시간으로 나눌 수 있다.
2. 기계용 시간은 EPOCK(1970년 1월1일 0시0분0초)부터 현재까지의 TimeStamp를 표현한다.
3. 인류용 시간은 우리가 흔히 사용하는 연,월,일,시,분,초 등을 표현한다.
4. TimeStamp는 Instant를 사용한다.
5. 특정 날짜(LocalDate), 시간(LocalTime), 일시(LocalDateTime)을 사용할 수 있다.
6. 기간을 표현할 때는 Duration(시간 기반)과 Period(날짜 기반)를 사용할 수 있다.
7. DateTimeFormatter를 사용해서 일시를 특정한 문자열로 포매팅할 수 있다.
| instant 활용
예시 ( 시간을 재거나 method 실행 시간을 측정할 때 사용 (기계용) )
Instant instant = Instant.now();
System.out.println(instant);
ZoneId zone = ZoneId.systemDefault();
System.out.println(zone);
ZonedDateTime zonedDateTime = instant.atZone(zone);
System.out.println(zonedDateTime);
| LocalDateTime
인간용
서버에 배포가 되면 서버가 실행되는 국가에 따라서 시간이 auto setting 되기 때문에 주의한다.
method
- of(int Month, int,int,int,int)
-> of를 사용하여 년,월,일,시를 설정할 수 있다.
- now()
->현재 시스템 Zone에 해당하는 (로컬) 일시를 return한다.
- ZonedDateTime.of(int Month,int,int,int,int,ZoneId)
->특정 Zone의 특정 일시를 return한다.
| 기간을 표현하는 방법 (Period 와 Duration)
- Period / Duration.between()
->인간용 비교
Period between = Period.between(today,birthDay);
System.out.println(between.get(ChronoUnit.DAYS));
Period 생일을 활용한 예시
LocalDate today = LocalDate.now();
LocalDate myBirthDay = LocalDate.of(2020, Month.AUGUST, 23); //생일 setting
//case 1 between()을 활용한 예시
Period period = Period.between(today, myBirthDay);
System.out.println(period.getDays());
//case 2 until()을 활용한 예시
Period until = today.until(myBirthDay);
System.out.println(until.getDays());
->Period 객체를 생성 후 between() OR until() & getDays() 를 활용하여 날짜가 얼마나 남은지 계산할 수 있다.
- Duration
->기계용 비교
//기계용 ( 메서드 시간 측정 등 )
Instant now2 = Instant.now();
//현재 초 부터 10초 차이가 나도록 더해줌
Instant plus = now2.plus(10,ChronoUnit.SECONDS);
Duration between = Duration.between(now2, plus);
System.out.println(between.getSeconds());
//결과
10
| 문자열 입력 OR 출력
//format
LocalDateTime now3 = LocalDateTime.now();
DateTimeFormatter MMddyyyy = DateTimeFormatter.ofPattern("yyyy/MM/dd");
System.out.println(now3.format(MMddyyyy));
//결과
2020/08/01
custom하게 pattern을 설정해줄 경우 LocalDateTime 으로 ofPattern() 메서드에 출력하고자 하는 형식을 지정해주고
LocalDateTime 객체의 format() 메서드를 호출하면 된다.
참고 Doc
| 사용자 입력 값(문자열) 파싱
- parse
사용자가 원하는 형태인 날짜 형식으로 값을 뽑아내고 싶다면 parse 를 사용하여 파싱한다.
//parse
//사용자가 문자열로 입력 값을 입력하면 -> 원하는 형식을 지정해주면 파싱되어 출력해준다.
DateTimeFormatter MMddyyyy2 = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate parse = LocalDate.parse("1993/08/23",MMddyyyy2);
System.out.println(parse);
//결과
1993-08-23 // 문자열을 날짜 형식으로 출력한다
| Date & Instant Type Change 호환성 레거시 API 지원
//Date와의 호환성
Date date = new Date(); //date 객체 생성
Instant instant3 = date.toInstant(); //date객체를 Instant로 전환
Date newDate = Date.from(instant3); // Instant객체를 from() 메서드를 활용하여 Date객체로 전환
-> Date 객체와 Instant 객체는 서로 호환되어 타입을 바꿀 수 있다.
또한
-
GregorianCalendar와 Date 타입의 인스턴스를 Instant나 ZonedDateTime으로 변환 가능.
-
java.util.TimeZone에서 java.time.ZoneId로 상호 변환 가능하다.
ZoneId newZoneAPI = TimeZone.getTimeZone("PST").toZoneId();
TimeZone legacyZoneAPI = TimeZone.getTimeZone(newZoneAPI);
'Java > Java8' 카테고리의 다른 글
스트림과 병렬 처리 (0) | 2021.05.29 |
---|---|
[java] and(), or(), negate() 디폴트 메소드와 isEqual()정적 메소드 (0) | 2020.10.28 |
[Java8]LocalDateTime이란? (0) | 2020.08.22 |