62
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

[Swift] 時刻の差分を取得し、いい感じに表示するDate Extension

はじめに

Twitterの通知のように通知がつくられた時刻と現在時刻の差分を取って、いいかんじ(◯時間前、◯日前)に表示しようとして考えていたときに、stack over flowにすばらしい解答があったので、備忘録の意味を込めてシェアしたいと思います。
Leo Dabusさんに感謝
Getting the difference between two NSDates in (months/days/hours/minutes/seconds)

NSDateでの比較で当初書いていた記事に対して、Swift3でのDateの比較をコメントいただいた@rd0501 さんありがとうございます。

Date Extension

DateExtension.swift
extension Date {

    func offsetFrom() -> String {
        if yearsFrom()   > 0 { return "\(yearsFrom())年前"   }
        if monthsFrom()  > 0 { return "\(monthsFrom())ヶ月前"  }
        if weeksFrom()   > 0 { return "\(weeksFrom())週間前"   }
        if daysFrom()    > 0 { return "\(daysFrom())日前"    }
        if hoursFrom()   > 0 { return "\(hoursFrom())時間前"   }
        if minutesFrom() > 0 { return "\(minutesFrom())分前" }
        if secondsFrom() > 0 { return "\(secondsFrom())秒前" }
        return ""
    }

    func yearsFrom() -> Int {
        return Calendar.current.dateComponents([.year], from: self, to: Date()).year ?? 0
    }
    func monthsFrom() -> Int {
        return Calendar.current.dateComponents([.month], from: self, to: Date()).month ?? 0
    }
    func weeksFrom() -> Int {
        return Calendar.current.dateComponents([.weekOfYear], from: self, to: Date()).weekOfYear ?? 0
    }
    func daysFrom() -> Int {
        return Calendar.current.dateComponents([.day], from: self, to: Date()).day ?? 0
    }
    func hoursFrom() -> Int {
        return Calendar.current.dateComponents([.hour], from: self, to: Date()).hour ?? 0
    }
    func minutesFrom() -> Int {
        return Calendar.current.dateComponents([.minute], from: self, to: Date()).minute ?? 0
    }
    func secondsFrom() -> Int {
        return Calendar.current.dateComponents([.second], from: self, to: Date()).second ?? 0
    }

}

使い方

たとえば現在時刻との差分から表示したいと場合、以下のように表記します。

//timeという2016/4/9 8:00:00 という時刻のDate型の変数があるとします。

let year = time.yearFrom() // -> 0年
let days = time.daysFrom() // 1日
let duration = time.offsetFrom() // -> 1日前

追記 任意の2つの時刻の間の時間をいい感じに表示したい場合

DateExtension.swift
extension Date {
    /// Returns the amount of years from another date
    func years(from date: Date) -> Int {
        return Calendar.current.dateComponents([.year], from: date, to: self).year ?? 0
    }
    /// Returns the amount of months from another date
    func months(from date: Date) -> Int {
        return Calendar.current.dateComponents([.month], from: date, to: self).month ?? 0
    }
    /// Returns the amount of weeks from another date
    func weeks(from date: Date) -> Int {
        return Calendar.current.dateComponents([.weekOfMonth], from: date, to: self).weekOfMonth ?? 0
    }
    /// Returns the amount of days from another date
    func days(from date: Date) -> Int {
        return Calendar.current.dateComponents([.day], from: date, to: self).day ?? 0
    }
    /// Returns the amount of hours from another date
    func hours(from date: Date) -> Int {
        return Calendar.current.dateComponents([.hour], from: date, to: self).hour ?? 0
    }
    /// Returns the amount of minutes from another date
    func minutes(from date: Date) -> Int {
        return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
    }
    /// Returns the amount of seconds from another date
    func seconds(from date: Date) -> Int {
        return Calendar.current.dateComponents([.second], from: date, to: self).second ?? 0
    }
    /// Returns the a custom time interval description from another date
    func offset(from date: Date) -> String {
        if years(from: date)   > 0 { return "\(years(from: date))年前"   }
        if months(from: date)  > 0 { return "\(months(from: date))月前"  }
        if weeks(from: date)   > 0 { return "\(weeks(from: date))週前"   }
        if days(from: date)    > 0 { return "\(days(from: date))日前"    }
        if hours(from: date)   > 0 { return "\(hours(from: date))時間前"   }
        if minutes(from: date) > 0 { return "\(minutes(from: date))分前" }
        if seconds(from: date) > 0 { return "\(seconds(from: date))秒前" }
        return ""
    }
}

使い方


//timeという2016/4/9 8:00:00 という時刻のDate型の変数があるとします。そのtimeと2015/4/8 8:00:00 という時刻のpastTimeというDate型の変数と比較したい場合

let year = time.years(from: pastTime) // -> 1
let offset = time.offset(from: pastTime) // -> 1年前

@ykws さん
ご指摘ありがとうございます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
62
Help us understand the problem. What are the problem?