반응형
Java Date 관련 흐름순
[java.util.Date](http://java.util.Date)
→ java.util.Calendar
→ java.time(org.joda.time)
Calender, Date 를 피하는 이유
불변 객체가 아니다
- set으로 변경이 가능하다는 점은 누군가 악의적으로 변경할 수 있기 때문에 get/set method에서 직접 Date 클래스를 사용하는 것이 위험하다
- Calendar 객체나 Date 객체가 여러 객체에서 공유되면 한 곳에서 바꾼 값이 다른 곳에 영향을 미치는 부작용이 생길 수 있다.
- C#, Python 같은 언어에서는 날짜 클래스가 한 번 생성된 이후에는 내부 속성을 변경할 수 없다.
- set으로 변경이 가능하다는 점은 누군가 악의적으로 변경할 수 있기 때문에 get/set method에서 직접 Date 클래스를 사용하는 것이 위험하다
상수필드 남용
- calendar.add(Calendar.SECOND, 2);
- 첫 번째 파라미터에 Calendar.JUNE과 같이, 전혀 엉뚱한 상수가 들어가도 이를 컴파일 시점에서 확인할 방법이 없다.
- Calendar 클래스에는 많은 int 상수가 쓰였는데, 월, 요일 지정 등에서도 많은 혼란을 유발한다.
헷갈리는 월 지정
1월을 0으로 표현하는 문제, Calendar.JUNE로 월을 지정하지만 실질적인 값은 5 (≠6)인 문제
JDK 1.0에서 Date 클래스는 1월을 0으로 표현했고, JDK 1.1부터 포함된 Calendar 클래스도 이러한 관례를 답습하였음.
2020년 6월 4일을 표현하는 코드를 아래와 같이 쓰는 실수를 많은 개발자들이 반복하고 있음. (설마 나만?)
// o calendar.set(2020, Calendar.JUNE, 4); // x calendar.set(2020, 6, 4); // 가독성을 높이기 위한 꼼수 calendar.set(2020, 6 - 1, 4);
2020년 12월 31을 지정하려고 했지만 결과는 2021년 1월 31일이 나온다. (컴파일러에서 오류를 반환하지 않기 때문에 이런 실수를 인지하기 더욱 어렵다)
@Test public void PublicTest() throws Exception { Calendar calendar = Calendar.getInstance(); calendar.set(2020, 12, 31); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); System.out.println(sdf.format(calendar.getTime())); }
일관성 없는 요일 상수
- 어디서는 일요일이 0, 어디서는 일요일이 1
Calendar.get(Calendar.DAY_OF_WEEK)
함수에서 반환한 요일은 int값으로, 일요일이 1로 표현된다.- 보통
Calendar.SUNDAY
상수와 비교해서 확인한다. 그런데calendar.getTime()
메소드로 Date 객체를 얻어와서Date.getDay()
메소드로 요일을 구하면 일요일은 0이 된다.
Date와 Calendar 객체의 역할 분담
- 년, 월, 일 계산은 Date 클래스만으로는 부족해서 왔다갔다 하는 문제
- Calendar객체를 생성하고 Date객체를 생성하는 프로세스를 거치기 때문에 번거롭고 생성비용이 높다.
LocalDate, LocalTime, LocalDateTime
- 위와 같은 문제를 해결하기 위해서 JAVA 8 버전부터는
LocalDate
,LocalTime
,LocalDateTime
라는 클래스가 생겼다.joda time
의 영향을 받아 비슷하게 설계되었다고 한다.- 그 밖에
Time and Money
라이브러리나ICU
등 여러 오픈소스 라이브러리를 참고했다고 한다.
- ISO 8601
사용법
현재 날짜 & 시간
@Test
public void PublicTest() throws Exception {
// LocalDate
LocalDate ld = LocalDate.now();
System.out.println(ld); // 2020-06-04
ld = LocalDate.of(2020, 6, 4);
System.out.println(ld); // 2020-06-04
// LocalTime
LocalTime lt = LocalTime.now();
System.out.println(lt); // 16:51:55.428
// 4번째 인자는 nanoSecond, 생략 가능
lt = LocalTime.of(14, 01, 02, 03);
System.out.println(lt); // 14:01:02.000000003
// LocalDateTime
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt); // 2020-06-03T17:00:04.808
ldt = LocalDateTime.of(2020, 6, 3, 14, 1, 2, 3);
System.out.println(ldt); // 2020-06-03T14:01:02.000000003
}
날짜계산
@Test
public void PublicTest() throws Exception {
// plus, minus
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt); // 2020-06-03T17:08:20.876
ldt = ldt.plusYears(1);
System.out.println(ldt); // 2021-06-03T17:08:20.876
ldt = ldt.plusMonths(1);
System.out.println(ldt); // 2021-07-03T17:08:20.876
ldt = ldt.plusWeeks(1);
System.out.println(ldt); // 2021-07-10T17:08:20.876
ldt = ldt.plusDays(1);
System.out.println(ldt); // 2021-07-11T17:08:20.876
ldt = ldt.plusHours(1);
System.out.println(ldt); // 2021-07-11T18:08:20.876
ldt = ldt.plusMinutes(1);
System.out.println(ldt); // 2021-07-11T18:09:20.876
ldt = ldt.plusSeconds(1);
System.out.println(ldt); // 2021-07-11T18:09:21.876
ldt = ldt.plusNanos(1);
System.out.println(ldt); // 2021-07-11T18:09:21.876000001
}
날짜 & 시간 비교
@Test
public void PublicTest() throws Exception {
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt); // 2020-06-03T17:17:50.195
LocalDateTime before = LocalDateTime.of(2019, 6, 4, 14, 1, 2);
System.out.println(before); // 2019-06-04T14:01:02
LocalDateTime after = LocalDateTime.of(2021, 6, 4, 14, 1, 2);
System.out.println(after); // 2021-06-04T14:01:02
System.out.println(ldt.isBefore(before)); // false
System.out.println(ldt.isBefore(after)); // true
System.out.println(ldt.isAfter(before)); // true
System.out.println(ldt.isAfter(after)); // false
System.out.println(ldt.equals(ldt)); // true
}
날짜 차이 계산
@Test
public void PublicTest() throws Exception {
LocalDate start = LocalDate.now();
System.out.println(start); // 2020-06-03
LocalDate end = LocalDate.of(2021, 6, 1);
System.out.println(end); // 2021-06-01
Period period = Period.between(start, end);
System.out.println(period.getYears()); // 0
System.out.println(period.getMonths()); // 11
System.out.println(period.getDays()); // 29
}
@Test
public void PublicTest() throws Exception {
LocalDate start = LocalDate.now();
System.out.println(start); // 2020-06-03
LocalDate end = LocalDate.of(2021, 6, 1);
System.out.println(end); // 2021-06-01
System.out.println(ChronoUnit.DAYS.between(start, end)); // 363
}
시간 차이 계산
@Test
public void PublicTest() throws Exception {
LocalTime start = LocalTime.now();
System.out.println(start); // 18:42:48.674
LocalTime end = LocalTime.of(23, 5, 11);
System.out.println(end); // 23:05:11
Duration duration = Duration.between(start, end);
System.out.println(duration.getSeconds()); // 15742
}
날짜 포맷
@Test
public void PublicTest() throws Exception {
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"))); // 2020-06-03 06:45:18
System.out.println(ldt.format(DateTimeFormatter.ofPattern("yyyy년 MM월 dd일 hh시 mm분 ss초"))); // 2020년 06월 03일 06시 45분 18초
}
날짜 변환
@Test
public void PublicTest() throws Exception {
String date = "2020-06-03";
System.out.println(LocalDate.parse(date)); // 2020-06-03
System.out.println(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"))); // 2020-06-03
}
참고
[1] : https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html
반응형
'Programming > JAVA' 카테고리의 다른 글
자바(JAVA) 직렬화, 역직렬화 (1) | 2023.10.31 |
---|---|
[JPA] @CreatedBy, @LastModifiedBy 를 위한 AuditorAware 적용 (0) | 2022.03.30 |
[JAVA] XPath 사용 중 The method getTextContent() is undefined for the type Node 에러를 만났을 때 해결하는 방법 (0) | 2018.12.01 |