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" | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
I get different results in return, can you tell me what causes this? |
This comment has been minimized.
This comment has been minimized.
Swift 2 updated: https://gist.github.com/jacks205/4a77fb1703632eb9ae79 |
This comment has been minimized.
This comment has been minimized.
With translation support https://gist.github.com/arnaudlamy/dbba08f7dd82cabd191f05d4546871e0 |
This comment has been minimized.
This comment has been minimized.
Hi, do you think we could have a version for Swift 3 ? Thx |
This comment has been minimized.
This comment has been minimized.
@sebastienboulogne here you go, ported to Swift 3. |
This comment has been minimized.
This comment has been minimized.
Swift 3
|
This comment has been minimized.
This comment has been minimized.
Awesome! You just saved me an hour. |
This comment has been minimized.
This comment has been minimized.
Perfect thanks a bunch! |
This comment has been minimized.
This comment has been minimized.
Great, |
This comment has been minimized.
This comment has been minimized.
Very Nice! |
This comment has been minimized.
This comment has been minimized.
Sweet! |
This comment has been minimized.
This comment has been minimized.
I made a Swift 3 framework for this. Has support for CocoaPods, Carthage, SPM, all platforms (iOS, macOS, tvOS, watchOS), and 42 localizations. Check it out and let me know what you think! https://github.com/toddkramer/LocalizedTimeAgo |
This comment has been minimized.
This comment has been minimized.
Thanks |
This comment has been minimized.
This comment has been minimized.
Using Date instead of NSDate:
|
This comment has been minimized.
This comment has been minimized.
thank you, guys! |
This comment has been minimized.
This comment has been minimized.
@heinrisch |
This comment has been minimized.
This comment has been minimized.
I rewrote this to be more swift-y because I needed future dates as well. Naming could be better I guess
https://gist.github.com/jinthagerman/009c85b7bbd0a40dcbba747e89a501bf |
This comment has been minimized.
This comment has been minimized.
Golden. Thanks for the time saver. If anyone found themselves here and needed usage:
|
This comment has been minimized.
This comment has been minimized.
Here's a another version import Foundation
extension Date {
fileprivate struct Item {
let multi: String
let single: String
let last: String
let value: Int?
}
fileprivate var components: DateComponents {
return Calendar.current.dateComponents(
[.minute, .hour, .day, .weekOfYear, .month, .year, .second],
from: Calendar.current.date(byAdding: .second, value: -1, to: Date())!,
to: self
)
}
fileprivate var items: [Item] {
return [
Item(multi: "years ago", single: "1 year ago", last: "Last year", value: components.year),
Item(multi: "months ago", single: "1 month ago", last: "Last month", value: components.month),
Item(multi: "weeks ago", single: "1 week ago", last: "Last week", value: components.weekday),
Item(multi: "days ago", single: "1 day ago", last: "Last day", value: components.day),
Item(multi: "minutes ago", single: "1 minute ago", last: "Last minute", value: components.minute),
Item(multi: "seconds ago", single: "Just now", last: "Last second", value: components.second)
]
}
public func timeAgo(numericDates: Bool = false) -> String {
for item in items {
switch (item.value, numericDates) {
case let (.some(step), _) where step == 0:
continue
case let (.some(step), true) where step == 1:
return item.last
case let (.some(step), false) where step == 1:
return item.single
case let (.some(step), _):
return String(step) + " " + item.multi
default:
continue
}
}
return "Just now"
}
}
print(Calendar.current.date(byAdding: .day, value: 1, to: Date())!.timeAgo()) |
This comment has been minimized.
This comment has been minimized.
A Swift 4 version without force unwrapping:
|
This comment has been minimized.
This comment has been minimized.
Sorry for interrupting the party, but seems like "time ago" feature is implemented in DateTools with locales and just works: let timeAgoDate = 2.days.earlier
print("Time Ago: ", timeAgoDate.timeAgoSinceNow)
print("Time Ago: ", timeAgoDate.shortTimeAgoSinceNow)
//Output:
//Time Ago: 2 days ago
//Time Ago: 2d |
This comment has been minimized.
This comment has been minimized.
The framework looks nice. However, sometimes only a feature is needed, not the whole framework = why to buy the whole cow if you need only milk. |
This comment has been minimized.
This comment has been minimized.
This is my version. It is based on @dariukas, but fixes some bugs import Foundation
extension Date {
///
/// Provides a humanised date. For instance: 1 minute, 1 week ago, 3 months ago
///
/// - Parameters:
// - numericDates: Set it to true to get "1 year ago", "1 month ago" or false if you prefer "Last year", "Last month"
///
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)
//print("")
//print(components)
if let year = components.year {
if (year >= 2) {
return "\(year) years ago"
} else if (year >= 1) {
return numericDates ? "1 year ago" : "Last year"
}
}
if let month = components.month {
if (month >= 2) {
return "\(month) months ago"
} else if (month >= 1) {
return numericDates ? "1 month ago" : "Last month"
}
}
if let weekOfMonth = components.weekOfMonth {
if (weekOfMonth >= 2) {
return "\(weekOfMonth) weeks ago"
} else if (weekOfMonth >= 1) {
return numericDates ? "1 week ago" : "Last week"
}
}
if let day = components.day {
if (day >= 2) {
return "\(day) days ago"
} else if (day >= 1) {
return numericDates ? "1 day ago" : "Yesterday"
}
}
if let hour = components.hour {
if (hour >= 2) {
return "\(hour) hours ago"
} else if (hour >= 1) {
return numericDates ? "1 hour ago" : "An hour ago"
}
}
if let minute = components.minute {
if (minute >= 2) {
return "\(minute) minutes ago"
} else if (minute >= 1) {
return numericDates ? "1 minute ago" : "A minute ago"
}
}
if let second = components.second {
if (second >= 3) {
return "\(second) seconds ago"
}
}
return "Just now"
}
}
|
This comment has been minimized.
This comment has been minimized.
@merlos nice, thank you ! |
This comment has been minimized.
This comment has been minimized.
@merlos awesome! thank you |
This comment has been minimized.
This comment has been minimized.
My version in Swift 4.2:
|
This comment has been minimized.
cool, do you have a gist that considers future dates too? "In a day", "In 1 day", "In 2 weeks"