Swift Convert Time to Time Ago

Swift display time ago from Date (NSDate)


If you just want a Time Ago extension for Date go to the bottom of the answer /p>

I'll show you an example just to get seconds ago and after I'll show your extension updated.

Note: you can use directly the date from Pase if you want:

if let pastDate = (object?["createdAt"] as? Date) {
cell.TimeAgo.text = pastDate.timeAgoDisplay()
}

Since Swift 5.1

Example how to display seconds ago with Swift 5.1:

Since iOS13 Apple introduce a new class RelativeDateTimeFormatter

extension Date {
func timeAgoDisplay() -> String {
let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .full
return formatter.localizedString(for: self, relativeTo: Date())
}
}

This class will allow you to get a time ago string based on your language. It automatically select the right unit of time based on your interval, here is an example:

|--------------------------|------------------|
| Time interval in seconds | Display |
|--------------------------|------------------|
| -6 | 6 seconds ago |
| -60 | 1 minute ago |
| -600 | 10 minutes ago |
| -6000 | 1 hour ago |
| -60000 | 16 hours ago |
|--------------------------|------------------|

You'll notice that it handle automatically plurals for you.

Swift 3 or Swift 4

Example how to get seconds ago with Swift 3 or Swift 4:

First: To get the number of seconds ago we need to check if we have one minutes or less, to get the current Date minus one minute you can write that:

let minuteAgo = calendar.date(byAdding: .minute, value: -1, to: Date())!

Second: Now compare the 2 dates! (In the case of your extension we replace yourDate by self) and get the difference between this 2 dates.

if (minuteAgo < yourDate) {
let diff = Calendar.current.dateComponents([.second], from: yourDate, to: Date()).second ?? 0
print("\(diff) sec ago")
}

That's all, now you can print the time ago !

So your extension is like this:
(This is a simple extension to get the time ago)

extension Date {
func timeAgoDisplay() -> String {

let calendar = Calendar.current
let minuteAgo = calendar.date(byAdding: .minute, value: -1, to: Date())!
let hourAgo = calendar.date(byAdding: .hour, value: -1, to: Date())!
let dayAgo = calendar.date(byAdding: .day, value: -1, to: Date())!
let weekAgo = calendar.date(byAdding: .day, value: -7, to: Date())!

if minuteAgo < self {
let diff = Calendar.current.dateComponents([.second], from: self, to: Date()).second ?? 0
return "\(diff) sec ago"
} else if hourAgo < self {
let diff = Calendar.current.dateComponents([.minute], from: self, to: Date()).minute ?? 0
return "\(diff) min ago"
} else if dayAgo < self {
let diff = Calendar.current.dateComponents([.hour], from: self, to: Date()).hour ?? 0
return "\(diff) hrs ago"
} else if weekAgo < self {
let diff = Calendar.current.dateComponents([.day], from: self, to: Date()).day ?? 0
return "\(diff) days ago"
}
let diff = Calendar.current.dateComponents([.weekOfYear], from: self, to: Date()).weekOfYear ?? 0
return "\(diff) weeks ago"
}
}

To use it, this is very straightforward:

var now = Date()
now.timeAgoDisplay()

Swift convert time to time ago

I'll just update the Truongky's answer for Swif 3:

extension Date {

func getElapsedInterval() -> String {

let interval = Calendar.current.dateComponents([.year, .month, .day], from: self, to: Date())

if let year = interval.year, year > 0 {
return year == 1 ? "\(year)" + " " + "year ago" :
"\(year)" + " " + "years ago"
} else if let month = interval.month, month > 0 {
return month == 1 ? "\(month)" + " " + "month ago" :
"\(month)" + " " + "months ago"
} else if let day = interval.day, day > 0 {
return day == 1 ? "\(day)" + " " + "day ago" :
"\(day)" + " " + "days ago"
} else {
return "a moment ago"

}

}
}

If you prefer a localizable response instead of only english this code will do the work

extension Date {
func getElapsedInterval() -> String {

var calendar = Calendar.current
calendar.locale = Locale(identifier: Bundle.main.preferredLocalizations[0])
// IF THE USER HAVE THE PHONE IN SPANISH BUT YOUR APP ONLY SUPPORTS I.E. ENGLISH AND GERMAN
// WE SHOULD CHANGE THE LOCALE OF THE FORMATTER TO THE PREFERRED ONE
// (IS THE LOCALE THAT THE USER IS SEEING THE APP), IF NOT, THIS ELAPSED TIME
// IS GOING TO APPEAR IN SPANISH

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.maximumUnitCount = 1
formatter.calendar = calendar

var dateString: String?

let interval = calendar.dateComponents([.year, .month, .weekOfYear, .day], from: self, to: Date())

if let year = interval.year, year > 0 {
formatter.allowedUnits = [.year] //2 years
} else if let month = interval.month, month > 0 {
formatter.allowedUnits = [.month] //1 month
} else if let week = interval.weekOfYear, week > 0 {
formatter.allowedUnits = [.weekOfMonth] //3 weeks
} else if let day = interval.day, day > 0 {
formatter.allowedUnits = [.day] // 6 days
} else {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: Bundle.main.preferredLocalizations[0]) //--> IF THE USER HAVE THE PHONE IN SPANISH BUT YOUR APP ONLY SUPPORTS I.E. ENGLISH AND GERMAN WE SHOULD CHANGE THE LOCALE OF THE FORMATTER TO THE PREFERRED ONE (IS THE LOCALE THAT THE USER IS SEEING THE APP), IF NOT, THIS ELAPSED TIME IS GOING TO APPEAR IN SPANISH
dateFormatter.dateStyle = .medium
dateFormatter.doesRelativeDateFormatting = true

dateString = dateFormatter.string(from: self) // IS GOING TO SHOW 'TODAY'
}

if dateString == nil {
dateString = formatter.string(from: self, to: Date())
}

return dateString!
}

Swift How to convert Parse createdAt time to time ago?

You can use NSCalendar isDateInToday to check if createdAt date is in same day as today, and use isDateInYesterday to check if it was yesterday. Just add a conditional and return a custom string for those conditions, for all other conditions just let date components formatter take care of it for you.

extension Formatter {
static let time: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .gregorian)
formatter.dateFormat = "h:mm a"
return formatter
}()
static let dateComponents: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.unitsStyle = .full
formatter.maximumUnitCount = 1
formatter.zeroFormattingBehavior = .default
formatter.allowsFractionalUnits = false
formatter.allowedUnits = [.year, .month, .weekOfMonth, .day, .hour, .minute, .second]
return formatter
}()
}

extension Date {

var time: String { return Formatter.time.string(from: self) }

var year: Int { return Calendar.autoupdatingCurrent.component(.year, from: self) }
var month: Int { return Calendar.autoupdatingCurrent.component(.month, from: self) }
var day: Int { return Calendar.autoupdatingCurrent.component(.day, from: self) }

var elapsedTime: String {
if timeIntervalSinceNow > -60.0 { return "Just Now" }
if isInToday { return "Today at \(time)" }
if isInYesterday { return "Yesterday at \(time)" }
return (Formatter.dateComponents.string(from: Date().timeIntervalSince(self)) ?? "") + " ago"
}
var isInToday: Bool {
return Calendar.autoupdatingCurrent.isDateInToday(self)
}
var isInYesterday: Bool {
return Calendar.autoupdatingCurrent.isDateInYesterday(self)
}
}

testing:

Calendar.autoupdatingCurrent.date(byAdding: .second, value: -59, to: Date())!
.elapsedTime // "Just Now"

Calendar.autoupdatingCurrent.date(byAdding: .minute, value: -1, to: Date())!
.elapsedTime // "Today at 5:03 PM"
Calendar.autoupdatingCurrent.date(byAdding: .hour, value: -1, to: Date())!
.elapsedTime // "Today at 4:04 PM"

Calendar.autoupdatingCurrent.date(byAdding: .day, value: -1, to: Date())!
.elapsedTime // "Yesterday at 5:02 PM"
Calendar.autoupdatingCurrent.date(byAdding: .weekOfYear, value: -1, to: Date())!
.elapsedTime // "1 week ago"

Calendar.autoupdatingCurrent.date(byAdding: .month, value: -2, to: Date())!
.elapsedTime // "2 months ago"
Calendar.autoupdatingCurrent.date(byAdding: .year, value: -1, to: Date())!
.elapsedTime // "1 year ago"

How to get 1 hour ago from a date in iOS swift?

For correct calculations involving NSDate that take into account all edge cases of different calendars (e.g. switching between day saving time) you should use NSCalendar class:

Swift 3+

let earlyDate = Calendar.current.date(
byAdding: .hour,
value: -1,
to: Date())

Older

// Get the date that was 1hr before now
let earlyDate = NSCalendar.currentCalendar().dateByAddingUnit(
.Hour,
value: -1,
toDate: NSDate(),
options: [])

Swift convert unix time to date and time gives incorrect year

Divide timestamp by 1000, because Date uses seconds and the timestamp was generated with milliseconds and use TimeInterval instead of Double.

    let dateVal = TimeInterval(1598859638000) / 1000.0


let date = Date(timeIntervalSince1970: TimeInterval(dateVal))
print(date, "date", date.timeIntervalSince1970)


let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone.init(abbreviation: "en")
dateFormatter.locale = Locale.init(identifier: "en")
dateFormatter.dateFormat = "E MMM d yyyy"
let outputDate = dateFormatter.string(from: date)
print(outputDate) // Mon Aug 31 2020

I guess your timestamp is generetd in a Java / Kotlin Applicatin. In java,
(new Date(1598859638000l)) yields Mon Aug 31 2020.

Swift convert unix time to date and time

To get the date to show as the current time zone I used the following.

if let timeResult = (jsonResult["dt"] as? Double) {
let date = NSDate(timeIntervalSince1970: timeResult)
let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.MediumStyle //Set time style
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle //Set date style
dateFormatter.timeZone = NSTimeZone()
let localDate = dateFormatter.stringFromDate(date)
}

Swift 3.0 Version

if let timeResult = (jsonResult["dt"] as? Double) {
let date = Date(timeIntervalSince1970: timeResult)
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.medium //Set time style
dateFormatter.dateStyle = DateFormatter.Style.medium //Set date style
dateFormatter.timeZone = self.timeZone
let localDate = dateFormatter.string(from: date)
}

Swift 5

if let timeResult = (jsonResult["dt"] as? Double) {
let date = Date(timeIntervalSince1970: timeResult)
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.medium //Set time style
dateFormatter.dateStyle = DateFormatter.Style.medium //Set date style
dateFormatter.timeZone = .current
let localDate = dateFormatter.string(from: date)
}

DateFormatter is Giving a Day before date

You are mixing a Date - which is a point in time - with a formatted Date string, which is something you can see on a watch or on a calendar.
Date is always referencing UTC (f.k.a. Greenwich Mean Time), so the output of print(date) will not print a calendar date but the UTC date and time.
If you convert that date to a "calendar entry" (by specifing a time zone etc.), you then will get the value that is displayed on your local watch, when in UTC its midnight on the 8th of March, 2021.
If you are living west of Greenwich, this will be the day before, because you are still on the 7th of March, waiting for the new day to arrive.



Related Topics



Leave a reply



Submit