본문 바로가기
Back-End (web)

[Kotlin] String to LocalDateTime parse

by 햄과함께 2019. 12. 7.
320x100

말머리가 Kotlin인 이유는 kotlin으로 작성했기 때문.. java라고 봐도 무방하다.

 

import java.time.LocalDateTime.of

class LocalDateTimeTest {

  @Test
  fun test() {

    // expect
    assertEquals(of(2019, 12, 4, 12, 3, 12), "2019-12-04 12:03:12".toLocalDateTime())
    assertEquals(of(2019, 12, 4, 12, 3), "2019-12-04 12:03".toLocalDateTime())
    assertEquals(of(2019, 12, 4, 12, 3,12,100000000), "2019-12-04 12:03:12.1".toLocalDateTime())
  }
}

테스트코드로 요구사항을 먼저 보자.

테스트에 사용되는 문자열들을 보면 "2019-12-04 12:03"은 중복으로 인식되어야 한다.

따라서 기본 패턴은 "yyyy-MM-dd HH:mm"이다.

그리고 뒤에 second가 선택적으로 들어가고 milli second 또한 선택적으로 문자열에 추가가 된다.

 

fun String.toLocalDateTime(): LocalDateTime? {
  if (this.isNullOrBlank()) return null

  return try {
    val formatter = DateTimeFormatterBuilder()
        .appendPattern("yyyy-MM-dd HH:mm[:ss]") // #1
        .appendFraction(ChronoField.MILLI_OF_SECOND, 0, 9, true) // #2
        .toFormatter()

    return LocalDateTime.parse(this, formatter)
  } catch (e: DateTimeParseException) {
    null
  }
}

함수는 문자열.toLocalDateTime() 과 같이 확장함수로 만들었다.

 #1  appendPattern으로 기본 패턴인 "yyyy-MM-dd HH:mm"을 인식하게 해주었다. 그리고 "[:ss]"를 추가함으로서 second가 선택적으로 파싱되어야 된다는걸 명시했다.

 #2  appendFraction을 이용하여 milli second에 해당하는 0~9까지의 숫자 또한 선택적으로 추가됨을 명시했다. 4번째 파라미터는 decimal point symbol이 있는지를 의미하는 것으로 "2019-12-04 12:03:12.1" 와 같이 초 뒤에 .1 과 같이 . 이 들어가므로 true로 명시해줬다.

 

위와 같이 작성하고 테스트를 돌려보면 모두 성공하는것을 확인할 수 있다.


@Test
fun test() {

  // expect
  assertEquals(LocalDateTime.of(2019, 12, 4, 12, 3), 
        "2019-12-04 12:03:12".toLocalDateTime()?.withSecond(0)) // #1
  assertNotEquals(LocalDateTime.of(2019, 12, 4, 12, 3),
        "2019-12-04 12:03:12.1".toLocalDateTime()?.withSecond(0)) // #2
  assertEquals(LocalDateTime.of(2019, 12, 4, 12, 3),
        "2019-12-04 12:03:12.1".toLocalDateTime()?.truncatedTo(ChronoUnit.MINUTES)) // #3
}

 #1  withSecond(0) 을 추가했는데, 조건에 해당하는 문자열들을 모두 LocalDateTime으로 바꿔주기는 하지만 특정 시간대만 사용하고자 할 때 이 외 단위는 무시하기 위해 추가하였다. (optional한 문자열들을 인식만 할 뿐 LocalDateTime으로 바꿔줄 필요는 없을 때)

 #2  그러나 withSecond(0)는 second 단위에 대해서만 처리가 되기 때문에 milli second는 삭제하지 못한다.

 #3  특정 단위 이하를 모두 무시하고 싶을 때에는 truncatedTo(ChronoUnit.MINUTES) 를 사용한다. truncate는 자른다는 의미이기 때문에 인식하고 싶은 단위(ChronoUnit.MINUTES)를 파라미터로 넘겨준다.


참고소스(깃허브) : LocalDateTime, Testcode

320x100

'Back-End (web)' 카테고리의 다른 글

[MockK] JPA repository.save param assert  (1) 2019.12.09
[Test] webClient 통신 테스트 (mockServer)  (0) 2019.12.08
[JUnit5] @TestInstance  (0) 2019.12.04
[Intellij][Error] Update Error (heap size)  (0) 2019.11.18
[Kotlin] list.groupBy  (0) 2019.10.17

댓글