[Android] java.time 패키지 때문에 String to date casting이 안될 때
728x90
반응형

 

하나의 자료형을 다른 자료형으로 바꾸는 작업을 우리는 캐스팅이라고 한다. 우리나라말로는 형변환이라고도 한다. 기본적이지만 조금씩 헷갈려서 외우기 어려운 경우가 있다. 내가 그렇다. 맞다. 핑계다. 신경써서 외우질 않으니... 외우지 않는다면 정리라도 잘해보자. 이번에 다룰 주제는 String에서 Date로, 혹은 Date에서 String으로 캐스팅하는 방법이다.

 

⏰ 1. 서버로부터 들어온 date 정보를 살펴보기

이번에 작업할 대상은 아래와 같이 날짜 정보가 주어졌다.

"createdAt":"2021-03-29T08:57:57.000Z"

듣도 보도 못한 양식이지만 우리 선배님들께서 이런 양식도 포매팅을 하는 방법을 블로그에 많이 올려주셨다. DateTimeFormatter를 이용해서 포매팅을 해주자.

 

import java.time.LocalDate
import java.time.format.DateTimeFormatter

val dateInString = "2021-03-29T08:57:57.000Z"
val pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.000'Z'")
val convertedDate = LocalDate.parse(dateInString, pattern)
println("String to Date converted : $convertedDate")

 

그런데...

 

 

 

⏰ 2. Call requires API level 26 (current min is 23)

java.time 패키지 사용시 위와 같은 에러를 만날 수 있다. 필자의 경우 minSdkVersion이 "23"이다. java.time 패키지의 경우 API 26 이상을 요구한다. 그렇다면 분기처리(if / else) 처리를 할 것인가? 그것보다 나은 경우가 있다. API 26 이하 버전에서도 java.time 패키지를 원활하게 사용하기 위한 백포팅을 적용하면 된다. 안드로이드계의 아이언맨. 제이크 왓슨횽이 또 한건 해주었다.

// build.gradle (app)
implementation 'com.jakewharton.threetenabp:threetenabp:1.3.0'

// Application 클래스
override fun onCreate() {
    super.onCreate()
    AndroidThreeTen.init(this)
}

// 적용하고자 할 클래스 내부
import org.threeten.bp.LocalDate
import org.threeten.bp.format.DateTimeFormatter

참고로 백포팅(Backporting)은 하드웨어나 소프트웨어 등에서 두루 쓰인다. 상위 버전의 기능을 하위 버전에서 사용할 수 있게 만드는 것을 일컫는다.

 

 

 

⏰ 3.이제 진짜 date 정보를 convert 해보자

이제 준비가 되었으니 진짜 캐스팅을 해보자. 아래와 같이 진행해보니 자~알 된다.

import org.threeten.bp.LocalDate
import org.threeten.bp.format.DateTimeFormatter

val pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.000'Z'")
val date = LocalDate.parse(createdAt, pattern)
Log.d("LOG", date.toString())

// 출력
// 2021-03-29

 

 

 

⏰ 4. 만약 원하는 형태의 날짜 포맷으로 출력하고 싶다면

지금까지의 경우는 String을 date로 만든 것이다. date로 만든 것을 String으로 만들고 싶다면 어떻게 하면 좋을까? 지금까지 사용했던 parse 함수말고 format 함수를 사용하면 된다.

val date = LocalDate.parse(createdAt, pattern) // data 타입
val pattern2 = DateTimeFormatter.ofPattern("yyyy MM dd")
Log.d(this.javaClass.simpleName, ">>> ${date.format(pattern2)}")

// 시간까지 표현하고 싶다면
// LocalDate --> LocalDateTime

 

 

😭 Error case : No time-zone data files registered

위와 같은 에러가 나타날 경우, "AndroidThreeTen.init(this)"를 제대로 해주지 않았을 가능성이 있다. 위 2번 항목을 다시 살펴보도록 하자.

 

 

😭 Error case : DateTimeParseException: Text '날짜 입력값' could not be parsed at index 19

쉽게 설명해서 19번째 포맷 양식이 잘못되었다는 뜻이다. 아래를 보면 '.'이 빠져있어서 에러가 나타났음을 알 수 있다. (당연하지만 첫글자는 0번째로 세어야 한다.)

// before
val pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss000'Z'")

// error
org.threeten.bp.format.DateTimeParseException: Text '2021-03-09T06:55:00.000Z' could not be parsed at index 19

// after
val pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.000'Z'")

 

 

참고자료
- [Android] Call requires API level 26 오류 해결
- [SLICK] DATETIME 로딩 시 오류
- ThreeTen Android Backport
- java.time.format.DateTimeParseException: Text could not be parsed at index 3
- How to format LocalDate to string?
- Kotlin Program To Convert String to Date
- How do I convert 2018-04-10T04:00:00.000Z string to DateTime?

 

728x90
반응형