Date ? Calendar? java.time? 뭘 써야 하나? : LocalDateTime

http://tcpschool.com/java/java_time_javaTime

https://d2.naver.com/helloworld/645609

 

LocalDateTime -> String

```java

LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))

```

 

LocalDateTime Json, Spring mapping

```java
// spring Controller에서 DATE_FORMAT형식->LocalDate로 받고 싶을 때
@DateTimeFormat(pattern = DATE_FORMAT)
private LocalDate fromUpdateDate;
 
// Jackson serialize/deserialize할 때 LocalDateTime<>DATE_TIME_FORMAT 형식 변환
@JsonFormat(pattern = DATE_TIME_FORMAT)
private LocalDateTime registrationDate;
 
// Thu, 21 Oct 2021 18:07:17 GMT 같은 형식 파싱할 때는 반드시 locale 지정한다. 현재 시스템이 KO 기준이면 "목, 21 10월..." 이렇게 파싱 시도한다.
```

 

DB에서 꺼낸 데이터가 LocalDateTime 타입 필드에 들어갈 때 에러나는 경우가 있음.

MyBatis 같은 경우 버전 3.4.5 이상은 MyBatis core에 LocalDateTimeTypeHandler 같은게 다 정의되어 있어서 자동으로 Timestamp로 변환이 되는 반면, 그 이전 버전은 Pre-defined Handler를 사용하기 위해서는  직접 dependency를 추가해주어야 한다.
 
아무튼 이런 Handler는 별도의 설정 없이 기본적으로 동작하도록 되어 있기 때문에(아마mybatis-spring-boot-starter일 듯?) LocalDateTime의 데이터를 맵에 넣어 DB에 INSERT 하거나 WHERE에 명시해도 잘 돌아간다.
 
그러나 DB에 저장되어 있는 날짜 데이터를 LocalDateTime 타입의 필드에 대입하는 경우(SELECT) 이런 에러가 발생한다.
```
java.lang.ClassNotFoundException: com.vividsolutions.jts.geom.Geometry
at org.apache.ibatis.type.LocalDateTimeTypeHandler.getNullableResult(LocalDateTimeTypeHandler.java:38) ~[mybatis-3.5.1.jar:3.5.1]
at org.apache.ibatis.type.LocalDateTimeTypeHandler.getNullableResult(LocalDateTimeTypeHandler.java:28) ~[mybatis-3.5.1.jar:3.5.1]
```
로그를 확인해보니 Handler는 잘 돌아가고 있으나 에러가 발생.

파라미터나 컬럼 네임을 아무리 바꿔보고 스택을 따라가봐도 원인을 모르겠다...
타입을 Date로 고치면 잘 된다. 그럼 LocalDateTime은 왜 안될까... 생각해보니 이게 Java8에서 추가된 클래스라 MyBatis나 JDBC같은게 Java8대응이 안되는 버전이면 Class를 못찾는게 아닐까? 하는 생각이 든다.
아... 그러고 보니 H2를 올릴 때 몇 가지 이슈 때문에 옛날 버전 H2를 사용하고 있었는데 이 것 때문이라는 느낌이 강하게 오는데
역시... H2 버전을 최신으로 올리고 다시 시도해보니 정상적으로 LocalDateTime에 매핑된다.
 
반나절 삽질의 결과...ㅠㅠ
 

Date format check

setter에서 데이터 넣기 전에 주로 체크.

```java

public void setQueryDate(String queryDate) {

    Date date = null;

    SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");

    try {

        date = format.parse(queryDate);

        if (!queryDate.equals(format.format(date))) {

            // 예를 들어 ss에 90이 들어오면 +1분 +30초로 자동으로 나뉘어지게 되는데, 이를 방지하기 위함.

            throw new ParseException(queryDate, 0);

        }

    } catch (ParseException e) {

        throw new RuntimeException(e);

    }

 

    if (queryDate.length() > 14)

        throw new StringIndexOutOfBoundsException();

    else

        this.queryDate = queryDate;

}

```

 

유틸리티로 따로 빼면

```java

public class DateFormatChecker {

    public static boolean isValidFormat(String strFormat, String strDate) {

        SimpleDateFormat format = new SimpleDateFormat(strFormat);

        try {

            Date date = format.parse(strDate);

            // 예를 들어 ss가 90초이면 +1분 +30초로 자동으로 나뉘어지게 되는데, 이를 방지하기 위함.

            return strDate.equals(format.format(date));

        } catch (ParseException e) {

            return false;

        }

    }

}

```

 

@TelegramField(position = 111, length = 5)

이런 식으로 중복되는걸 setter가 아니라 annotation으로 빼면 더 좋다.

DateFormatCheck나 size같은거...

 

*** timestamp millis 반환. 어떻게? ( 시간 측정 ? )

 

시간 비교는 ChronoUnit이 제일 직관적

https://www.baeldung.com/java-date-difference

'Java Stack > Java' 카테고리의 다른 글

[Effective Java] 3장 모든 객체의 공통 메서드  (0) 2019.12.04
[Effective Java] 2장 객체 생성과 파괴  (0) 2019.12.02
[Java] Enum  (0) 2019.06.06
[Java] Jackson ObjectMapper Serialization  (0) 2019.05.15
JVM 관련  (0) 2017.05.05