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

More than 1 year has passed since last update.


はじめに

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 さん

ご指摘ありがとうございます。