Skip to content

Instantly share code, notes, and snippets.

@minorbug
Created November 7, 2014 15:28
Show Gist options
  • Save minorbug/468790060810e0d29545 to your computer and use it in GitHub Desktop.
Save minorbug/468790060810e0d29545 to your computer and use it in GitHub Desktop.
"Time ago" function for Swift (based on MatthewYork's DateTools for Objective-C)
func timeAgoSinceDate(date:NSDate, numericDates:Bool) -> String {
let calendar = NSCalendar.currentCalendar()
let unitFlags = NSCalendarUnit.CalendarUnitMinute | NSCalendarUnit.CalendarUnitHour | NSCalendarUnit.CalendarUnitDay | NSCalendarUnit.CalendarUnitWeekOfYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitSecond
let now = NSDate()
let earliest = now.earlierDate(date)
let latest = (earliest == now) ? date : now
let components:NSDateComponents = calendar.components(unitFlags, fromDate: earliest, toDate: latest, options: nil)
if (components.year >= 2) {
return "\(components.year) years ago"
} else if (components.year >= 1){
if (numericDates){
return "1 year ago"
} else {
return "Last year"
}
} else if (components.month >= 2) {
return "\(components.month) months ago"
} else if (components.month >= 1){
if (numericDates){
return "1 month ago"
} else {
return "Last month"
}
} else if (components.weekOfYear >= 2) {
return "\(components.weekOfYear) weeks ago"
} else if (components.weekOfYear >= 1){
if (numericDates){
return "1 week ago"
} else {
return "Last week"
}
} else if (components.day >= 2) {
return "\(components.day) days ago"
} else if (components.day >= 1){
if (numericDates){
return "1 day ago"
} else {
return "Yesterday"
}
} else if (components.hour >= 2) {
return "\(components.hour) hours ago"
} else if (components.hour >= 1){
if (numericDates){
return "1 hour ago"
} else {
return "An hour ago"
}
} else if (components.minute >= 2) {
return "\(components.minute) minutes ago"
} else if (components.minute >= 1){
if (numericDates){
return "1 minute ago"
} else {
return "A minute ago"
}
} else if (components.second >= 3) {
return "\(components.second) seconds ago"
} else {
return "Just now"
}
}
@demonukg
Copy link

@merlos awesome! thank you

@rafalwojcik
Copy link

rafalwojcik commented Dec 4, 2018

My version in Swift 4.2:

import Foundation

extension Date {
    func timeAgo(numericDates: Bool) -> String {
        let calendar = Calendar.current
        let now = Date()
        let earliest = self < now ? self : now
        let latest =  self > now ? self : now

        let unitFlags: Set<Calendar.Component> = [.minute, .hour, .day, .weekOfMonth, .month, .year, .second]
        let components: DateComponents = calendar.dateComponents(unitFlags, from: earliest, to: latest)

        let year = components.year ?? 0
        let month = components.month ?? 0
        let weekOfMonth = components.weekOfMonth ?? 0
        let day = components.day ?? 0
        let hour = components.hour ?? 0
        let minute = components.minute ?? 0
        let second = components.second ?? 0

        switch (year, month, weekOfMonth, day, hour, minute, second) {
            case (let year, _, _, _, _, _, _) where year >= 2: return "\(year) years ago"
            case (let year, _, _, _, _, _, _) where year == 1 && numericDates: return "1 year ago"
            case (let year, _, _, _, _, _, _) where year == 1 && !numericDates: return "Last year"
            case (_, let month, _, _, _, _, _) where month >= 2: return "\(month) months ago"
            case (_, let month, _, _, _, _, _) where month == 1 && numericDates: return "1 month ago"
            case (_, let month, _, _, _, _, _) where month == 1 && !numericDates: return "Last month"
            case (_, _, let weekOfMonth, _, _, _, _) where weekOfMonth >= 2: return "\(weekOfMonth) weeks ago"
            case (_, _, let weekOfMonth, _, _, _, _) where weekOfMonth == 1 && numericDates: return "1 week ago"
            case (_, _, let weekOfMonth, _, _, _, _) where weekOfMonth == 1 && !numericDates: return "Last week"
            case (_, _, _, let day, _, _, _) where day >= 2: return "\(day) days ago"
            case (_, _, _, let day, _, _, _) where day == 1 && numericDates: return "1 day ago"
            case (_, _, _, let day, _, _, _) where day == 1 && !numericDates: return "Yesterday"
            case (_, _, _, _, let hour, _, _) where hour >= 2: return "\(hour) hours ago"
            case (_, _, _, _, let hour, _, _) where hour == 1 && numericDates: return "1 hour ago"
            case (_, _, _, _, let hour, _, _) where hour == 1 && !numericDates: return "An hour ago"
            case (_, _, _, _, _, let minute, _) where minute >= 2: return "\(minute) minutes ago"
            case (_, _, _, _, _, let minute, _) where minute == 1 && numericDates: return "1 minute ago"
            case (_, _, _, _, _, let minute, _) where minute == 1 && !numericDates: return "A minute ago"
            case (_, _, _, _, _, _, let second) where second >= 3: return "\(second) seconds ago"
            default: return "Just now"
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment