두 날짜 사이의 Day 차이 계산하기

SteadySlower·2022년 11월 14일
0
post-custom-banner

구현하고자 하는 기능

이번에 구현하고자 하는 기능은 각각의 단어장을 나타내는 Cell에 단어장을 만든 날짜를 표시하는 것입니다. 즉 오늘 만든 단어장이면 우하단에 今日(오늘)이 뜨도록 하고 어제 보다 이전에 만든 단어라면 n日前이라고 표시하는 기능입니다.

Date와 Calendar 그리고 DateComponents

각각의 정의

Date

공식 문서를 통해서 Date의 의미에 대해서 알아봅시다. 아래 공식문서에서 가져온 정의를 보면 Date는 calendar나 time zone에 독립적인 시간의 특정한 지점을 의미한다고 합니다. 예를 들면 Date()로 Date 객체를 하나 만들면 만든 시점의 특정한 시간을 의미하는 Date 객체가 하나 생기는 것이죠.

Calendar

반면에 Calendar의 정의를 보면 두 calendar unit 혹은 시간의 절대적 지점 (Date의 정의와 유사하죠?) 간의 관계를 정의하는 것입니다. 그리고 날짜들의 계산이나 비교를 위한 특징을 제공하죠.

DateComponent

마지막으로 DateComponent의 정의입니다. date 혹은 time인데 특정 단위 (연, 월, 날, 시간, 분)으로 정의된 객체입니다. 그리고 그 객체는 calendar system이나 time zone에서 정의됩니다.

약간 복잡한데요. 결국 DateComponents 객체는 Date와 동일하게 특정한 시간을 의미할 수 있습니다. 하지만 Calendar와 time zone에 의존하지 않는 Date 객체와는 다르게 Calendar에 의존하는 객체라는 차이점이 있습니다. 따라서 시간을 연, 월, 날 등의 단위로 분리해서 정의될 수 있는 것이죠.

또한 dateComponents는 한 시점 뿐만 아니라 시간의 양도 정의할 수 있습니다. 따라서 두 날짜 사이에 얼마만큼의 시간이 떨어져있는지도 나타낼 수 있습니다.

결론

공식문서에 의하면 Date는 시간 그 자체를 의미합니다. Calendar는 시간과 시간의 관계를 정의해주는 역할을 합니다. 따라서 우리의 기능 (오늘과 단어장을 만든 시간 사이의 날짜를 계산해주는 기능)은 오늘을 의미하는 Date 객체와 단어장을 만든 시간을 나타내는 Date 객체 2개를 가지고 Calendar를 이용해서 비교해주어야 합니다. 그리고 그 결과는 day 단위의 DateComponent 객체로 표현될 것입니다.

구현하기

두 Date 사이의 날짜 차이 구하기

Calendar에서는 두 Date 객체의 차이를 dateComponents 객체로 변환해주는 메소드가 있습니다. 아래 메소드를 사용하면 됩니다.

Calendar.current.dateComponents([.day], from: from, to: to).day

주의할 점!

하지만 단순하게 위 메소드만을 사용하면 안됩니다. 우리가 고려하고자 하는 것은 두 Date의 “날짜” 차이이지 정확한 시간의 차이가 아닙니다. 위 메소드만을 사용해서 비교하는 경우 시간까지 고려해서 계산하기 때문에 예를 들어 어제 오후에 저장한 단어장이 오늘 오전에 "오늘"로 표시되는 경우가 발생할 수도 있습니다.

따라서 시간 부분은 버리고 year-month-day만 가지고 계산을 해서 날짜 차이를 구하도록 하겠습니다. Calendar에는 DateComponent 객체를 다시 Date로 변경해주는 메소드가 있습니다. extension의 형태로 구현한 메소드는 아래와 같습니다.

// 시간 부분을 버리기
extension Date {
    var onlyDate: Date {
        let component = Calendar.current.dateComponents([.year, .month, .day], from: self)
        return Calendar.current.date(from: component) ?? Date()
    }
}
// 두 날짜 사이의 날짜 차이 구하기
extension Calendar {
    func getDateGap(from: Date, to: Date) -> Int {
        let fromDateOnly = from.onlyDate
        let toDateOnly = to.onlyDate
        return self.dateComponents([.day], from: fromDateOnly, to: toDateOnly).day ?? 0
    }
}
// String로 변경해서 사용
var dateText: String {
    let gap = Calendar.current.getDateGap(from: wordBook.createdAt, to: Date())
    return gap == 0 ? "今日" : "\(gap)日前"
}
profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.
post-custom-banner

0개의 댓글