[자바] 날짜 클래스

kwang·2023년 12월 17일
0

들어가기

자바 이전 버전에서는 Date 클래스와 Calender 클래스를 제공했으나 둘 다 직관적이지 않으며 달에 시작이 0부터인 점, 가변객체라는 등 불편한 점이 많았다.

따라서 자바 8에서는 Joda-Time이라는 서드파티 라이브러리를 인용해서 java.time 패키지를 추가했다.

특정 시점 날짜 관련 클래스

Temporal 인터페이스는 특정 시간을 모델링하는 객체의 값을 어떻게 일고 조작할지 정의하는 인터페이스며 자바8에서 제공된 클래스들은 해당 인터페이스를 구현한다.

LocalDate, LocalDateTime, LocalTime

우선 불변 객체이며 사람이 인지하는 시간 정보를 나타내는데 특화된 클래스이다.

정보 제공 메서드

메서드설명
getYear()년도 정보를 가져온다.
getMonth()월 정보를 가져온다.
getDayOfMonth()일 정보를 가져온다
getDayOfWeek()요일 정보를 가져온다.
getlengthOfMonth()해당 월에 마지막 일 정보를 가져온다.
getLeapYear()윤년 여부 정보를 가져온다.
get()인수로 요청한 TemporalField(인터페이스)에 맞는 타입에 값을 가져온다.

이처럼 날짜와 관련된 다양한 메서드들을 제공한다. 여기서 get()에 대해 간단히 추가 설명하자면 TemporalField를 구현한 ChronoField(Enum Class)를 이용해서 기본 제공 메서드외에 다양한 방법으로 시간정보를 가져올 수 있다.

날짜 조정

특정 시점에 시간을 변경하거나 몇 시간뒤 날짜와 같은 단순한 기능은 withAttribute 또는 minusAttribute, plusAttribute를 통해 변경할 수 있으며 모두 불변객체이므로 새로운 객체를 반환한다.

TemporalAdjusters

조금 더 복잡한 다음주 월요일, 특정 달의 마지막 날과 같이 복잡한 날짜 조정 기능을 제공하는 클래스이다.

아래의 현재 시점에 다음주 월요일을 구하는 예제를 확인해보자

fun main() {
    val now = LocalDate.now()
    val nextMonday = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY))
    println(nextMonday)
}

또한 커스텀한 날짜를 구하는 기능을 구현하고 싶다면 TemporalAdjuster 인터페이스를 구현해서 다음과 같은 다음 근무일을 구하는 날짜 계산기를 구현 수 있다.

class NextWorkingDay {
    companion object: TemporalAdjuster {
        override fun adjustInto(temporal: Temporal): Temporal {
            val dayOfWeek = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK))
            var dayToAdd: Long = 1
            if (dayOfWeek == DayOfWeek.FRIDAY) dayToAdd = 3
            else if(dayOfWeek == DayOfWeek.SATURDAY) dayToAdd = 2
            return temporal.plus(dayToAdd, ChronoUnit.DAYS)
        }
    }
}

날짜 포매팅

날짜 포매팅을 지원하는 가장 중요한 클래스는 DateTimeFormatter이다.
아래와 같이 다양한 포맷을 지원할 수 잇다.

fun main() {
    // 날짜타입을 원하는 포맷에 문자열로 변경하는 방법
    val now = LocalDate.now()
    val s1 = now.format(DateTimeFormatter.BASIC_ISO_DATE) // yyyyMMdd
    val s2 = now.format(DateTimeFormatter.ISO_LOCAL_DATE) // yyyy-MM-dd

    // 포맷에 맞는 문자열을 날짜 타입으로 변환하는 방법
    val parseDate = LocalDate.parse("20231217", DateTimeFormatter.BASIC_ISO_DATE)

    val formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy yyyy!!")
    val customFormat = now.format(formatter)

    val koreanFormatter = DateTimeFormatter.ofPattern("yyyy MMMM dd", Locale.KOREAN)
    val koreanDate = now.format(koreanFormatter)
}

Instant

기계에서 다루기 쉽도록 지원하는 날짜 타입이며 UTC 시간을 기준으로 특정 지점까지의 시간을 초로 표현한다. 또한 나노초(10억분의 1초)의 정밀도를 제공한다.

특정 기간 날짜 클래스

Duration 클래스는 나노초까지의 시간 간격을 나타낼수 있다.
Period 클래스는 일까지의 시간 간격을 나타낼 수 있다.

두 클래스는 특정 시점 간에 간격을 알거나 어느 한 시점에서 해당 기간 뒤에 전후 시간을 알 수 있는 기능을 지원한다.

val twoOfDays = Period.ofDays(2)
val dateNow = LocalDate.now()
val tomorrow = twoOfDays.addTo(dateNow)

다양한 시간대

세계에 각 나라마다 시간대가 다르다. 이를 자바8에서는 TimeZone을 대체할 수 있게 ZoneId 클래스를 지원한다. 해당 클래스는 불변클래스이며 '{지역}/{도시}' 와 같은 형식으로 이루어져 있다.

아래는 일반 날짜 클래스를 시간대 정보가 있는 날짜로 변경하는 방법이다.

fun main() {
    val zoneId = TimeZone.getDefault().toZoneId()

    val nowDate = LocalDate.now()
    val zoneNowDate = nowDate.atStartOfDay(zoneId)

    val nowDateTime = LocalDateTime.now()
    val zoneNowDateTime = nowDateTime.atZone(zoneId)
}

0개의 댓글