I have been researching, but I couldnt find exact solution for my problem. I have been trying to get 1 hour ago from a date. How can I achieve this in swift?
14 Answers
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: [])

- 18,693
- 1
- 17
- 24

- 170,431
- 36
- 387
- 313
-
1What is WrapComponents for? – Van Du Tran Jan 27 '16 at 21:13
-
1`.WrapComponents` means don't increment the day if adding an hour pushes you past midnight. I think it makes more sense to use `options: []`, like Deepak's answer at the bottom of the thread. – Robert Chen Apr 05 '16 at 19:04
-
For Swift3 ... let alteredDate = userCalendar.date(byAdding: .hour, value: -1, to: now) – Chris Allinson Dec 28 '16 at 12:18
Use this method and paste in your helper class.
Updated for Swift 3 and Xcode 8.3
class func timeAgoSinceDate(_ date:Date,currentDate:Date, numericDates:Bool) -> String {
let calendar = Calendar.current
let now = currentDate
let earliest = (now as NSDate).earlierDate(date)
let latest = (earliest == now) ? date : now
let components:DateComponents = (calendar as NSCalendar).components([NSCalendar.Unit.minute , NSCalendar.Unit.hour , NSCalendar.Unit.day , NSCalendar.Unit.weekOfYear , NSCalendar.Unit.month , NSCalendar.Unit.year , NSCalendar.Unit.second], from: earliest, to: latest, options: NSCalendar.Options())
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"
}
}
Use of this method:
var timeAgo:String=AppHelper.timeAgoSinceDate(date, numericDates: true)
Print("\(timeAgo)") // Ex- 1 hour ago

- 33,281
- 23
- 160
- 191

- 8,222
- 5
- 68
- 78
-
1
-
1
-
3Here it is as an extension of the NSDate class: https://gist.github.com/vikdenic/988d6f3920b7b7950d40 – vikzilla Mar 24 '16 at 00:39
-
Suggestions for *real Swift 3(+)* to get rid of `NS...` classes: `let earliest = min(now, date)` – `let latest = max(now, date)` – `let components = calendar.dateComponents([.minute , .hour , .day , .weekOfYear , .month , .year , .second], from: earliest, to: latest)` – vadian Jan 15 '19 at 10:59
-
1
Please read the NSDate
class reference.
let oneHourAgo = NSDate.dateWithTimeIntervalSinceNow(-3600)
should do it.
Or, for any NSDate
object:
let oneHourBack = myDate.dateByAddingTimeInterval(-3600)
Swift 4:
let oneHourAgo = NSDate(timeIntervalSinceNow: -3600)

- 22,770
- 10
- 62
- 73
-
-
6New syntax for the former is: `NSDate(timeIntervalSinceNow: -3600)` – William Entriken Nov 11 '15 at 14:51
According to your needs, you may choose one of the 3 following Swift 5 methods to get one hour ago from a Date
instance.
1. date(byAdding:value:to:wrappingComponents:)
Calendar
has a method called date(byAdding:value:to:wrappingComponents:)
. date(byAdding:value:to:wrappingComponents:)
has the following declaration:
func date(byAdding component: Calendar.Component, value: Int, to date: Date, wrappingComponents: Bool = default) -> Date?
Returns a new
Date
representing the date calculated by adding an amount of a specific component to a given date.
The Playground code below shows how to use it:
import Foundation
let now = Date()
let oneHourAgo = Calendar.current.date(byAdding: .hour, value: -1, to: now)
print(now) // 2016-12-19 21:52:04 +0000
print(String(describing: oneHourAgo)) // Optional(2016-12-19 20:52:04 +0000)
2. date(byAdding:to:wrappingComponents:)
Calendar
has a method called date(byAdding:to:wrappingComponents:)
. date(byAdding:value:to:wrappingComponents:)
has the following declaration:
func date(byAdding components: DateComponents, to date: Date, wrappingComponents: Bool = default) -> Date?
Returns a new
Date
representing the date calculated by adding components to a given date.
The Playground code below shows how to use it:
import Foundation
let now = Date()
var components = DateComponents()
components.hour = -1
let oneHourAgo = Calendar.current.date(byAdding: components, to: now)
print(now) // 2016-12-19 21:52:04 +0000
print(String(describing: oneHourAgo)) // Optional(2016-12-19 20:52:04 +0000)
Alternative:
import Foundation
// Get the date that was 1hr before now
let now = Date()
let components = DateComponents(hour: -1)
let oneHourAgo = Calendar.current.date(byAdding: components, to: now)
print(now) // 2016-12-19 21:52:04 +0000
print(String(describing: oneHourAgo)) // Optional(2016-12-19 20:52:04 +0000)
3. addingTimeInterval(_:)
(use with caution)
Date
has a method called addingTimeInterval(_:)
. addingTimeInterval(_:)
has the following declaration:
func addingTimeInterval(_ timeInterval: TimeInterval) -> Date
Return a new
Date
by adding aTimeInterval
to thisDate
.
Note that this method comes with a warning:
This only adjusts an absolute value. If you wish to add calendrical concepts like hours, days, months then you must use a
Calendar
. That will take into account complexities like daylight saving time, months with different numbers of days, and more.
The Playground code below shows how to use it:
import Foundation
let now = Date()
let oneHourAgo = now.addingTimeInterval(-3600)
print(now) // 2016-12-19 21:52:04 +0000
print(oneHourAgo) // 2016-12-19 20:52:04 +0000

- 1
- 1

- 89,880
- 29
- 256
- 218
-
Option one, `date(byAdding:value:to:wrappingComponents:)` seems like the best/simplest fit. It lets you add a single date component value to a date. – Duncan C Oct 13 '18 at 23:56
If you are using NSDate
you can do:
let date = NSDate()
date.dateByAddingTimeInterval(-3600)
It will change the date
object to be "1 hour ago".

- 71
- 1
- 5
Swift3:
let now = Date()
let tempCalendar = Calendar.current
let alteredDate = tempCalendar.date(byAdding: .hour, value: -1, to: now)

- 1,837
- 2
- 26
- 39
I achieve time ago functionality by creating extension of Date. Which is given below:
extension Date {
// Returns the number of years
func yearsCount(from date: Date) -> Int {
return Calendar.current.dateComponents([.year], from: date, to: self).year ?? 0
}
// Returns the number of months
func monthsCount(from date: Date) -> Int {
return Calendar.current.dateComponents([.month], from: date, to: self).month ?? 0
}
// Returns the number of weeks
func weeksCount(from date: Date) -> Int {
return Calendar.current.dateComponents([.weekOfMonth], from: date, to: self).weekOfMonth ?? 0
}
// Returns the number of days
func daysCount(from date: Date) -> Int {
return Calendar.current.dateComponents([.day], from: date, to: self).day ?? 0
}
// Returns the number of hours
func hoursCount(from date: Date) -> Int {
return Calendar.current.dateComponents([.hour], from: date, to: self).hour ?? 0
}
// Returns the number of minutes
func minutesCount(from date: Date) -> Int {
return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
}
// Returns the number of seconds
func secondsCount(from date: Date) -> Int {
return Calendar.current.dateComponents([.second], from: date, to: self).second ?? 0
}
// Returns time ago by checking if the time differences between two dates are in year or months or weeks or days or hours or minutes or seconds
func timeAgo(from date: Date) -> String {
if yearsCount(from: date) > 0 { return "\(yearsCount(from: date))years ago" }
if monthsCount(from: date) > 0 { return "\(monthsCount(from: date))months ago" }
if weeksCount(from: date) > 0 { return "\(weeksCount(from: date))weeks ago" }
if daysCount(from: date) > 0 { return "\(daysCount(from: date))days ago" }
if hoursCount(from: date) > 0 { return "\(hoursCount(from: date))hours ago" }
if minutesCount(from: date) > 0 { return "\(minutesCount(from: date))minutes ago" }
if secondsCount(from: date) > 0 { return "\(secondsCount(from: date))seconds ago" }
return ""
}
}
Then i get the time ago by calculating the difference between current date and specified date:
let timeAgo = Date().timeAgo(from: sender.date)

- 6,310
- 4
- 25
- 36
You can also use an operator
let date = Date()
let anHourAgo = date - TimeInterval(3600.0)
Apple Docs: https://developer.apple.com/documentation/foundation/date/2293436

- 4,912
- 2
- 25
- 33
for Swift 2:
extension NSDate {
func after(value: Int, calendarUnit:NSCalendarUnit) -> NSDate {
return calendar.dateByAddingUnit(calendarUnit, value: value, toDate: self, options: [])!
}
}
how to use:
let lastHour = NSDate().after(-1, calendarUnit: .Hour)

- 132,869
- 46
- 340
- 423

- 11
- 3
This works for iOS 13 / Swift 5. Credit goes to Sourabh Sharma
func timeAgoSinceNow(numericDates: Bool = true) -> String {
let calendar = Calendar.current
let now = Date()
let earliest = (now as NSDate).earlierDate(self)
let latest = (earliest == now) ? self : now
let components: DateComponents = (calendar as NSCalendar).components([NSCalendar.Unit.minute,
NSCalendar.Unit.hour,
NSCalendar.Unit.day,
NSCalendar.Unit.weekOfYear,
NSCalendar.Unit.month,
NSCalendar.Unit.year,
NSCalendar.Unit.second],
from: earliest,
to: latest,
options: NSCalendar.Options())
guard
let year = components.year,
let month = components.month,
let weekOfYear = components.weekOfYear,
let day = components.day,
let hour = components.hour,
let minute = components.minute,
let second = components.second
else { return "A while ago"}
if year >= 1 {
return year >= 2 ? "\(year) years ago" : numericDates ? "1 year ago" : "Last year"
} else if month >= 1 {
return month >= 2 ? "\(month) months ago" : numericDates ? "1 month ago" : "Last month"
} else if weekOfYear >= 1 {
return weekOfYear >= 2 ? "\(weekOfYear) weeks ago" : numericDates ? "1 week ago" : "Last week"
} else if day >= 1 {
return day >= 2 ? "\(day) days ago" : numericDates ? "1 day ago" : "Yesterday"
} else if hour >= 1 {
return hour >= 2 ? "\(hour) hours ago" : numericDates ? "1 hour ago" : "An hour ago"
} else if minute >= 1 {
return minute >= 2 ? "\(minute) minutes ago" : numericDates ? "1 minute ago" : "A minute ago"
} else {
return second >= 3 ? "\(second) seconds ago" : "Just now"
}
}
Usage:
var date = Date() // Or any date you wish to convert to text
print("\(date.timeAgoSinceNow())") // "Just Now"

- 619
- 1
- 8
- 18
Calendar.current.date( byAdding: .hour, value: -1, to: Date())

- 4,552
- 14
- 29
- 49

- 55
- 2
-
Please consider formatting your relevant parts of your answer as code. – WaitingForGuacamole Feb 23 '21 at 16:41
-
it does not look any improvement on the other answers provided previously – buzatto Feb 25 '21 at 01:40
In swift 5 You can use
let earlyDate = Calendar.current.date( byAdding: .hour, value: -1, to: Date())
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd HH:mm:ss"
let dateString = df.string(from: earlyDate!)
Out put will Be like bellow
Current DateTime--> 2019-12-20 09:40:08
One Hour Previous Date Time--> 2019-12-20 08:40:08

- 4,789
- 1
- 37
- 50
Details
- Xcode 11.4 (11E146), Swift 5.2
Solution
import Foundation
extension Date {
typealias Component = (value: Int, type: Calendar.Component)
init?(bySubtracting components: Component..., calendar: Calendar = Calendar.current, from date: Date) {
guard let date = date.subtract(components, calendar: calendar) else { return nil }
self = date
}
func subtract(_ components: Component..., calendar: Calendar = Calendar.current) -> Date? {
subtract(components, calendar: calendar)
}
func subtract(_ components: [Component], calendar: Calendar = Calendar.current) -> Date? {
components.reduce(self) { (result, component) -> Date? in
guard let date = result else { return nil }
return calendar.date(byAdding: component.type, value: (-1)*component.value, to: date)
}
}
static func beforeNow(difference component: Component..., calendar: Calendar = Calendar.current) -> Date? {
Date().subtract(component, calendar: calendar)
}
static func beforeNow(difference component: [Component], calendar: Calendar = Calendar.current) -> Date? {
Date().subtract(component, calendar: calendar)
}
}
extension Date {
static func - (date: Date, component: Date.Component) -> Date? { date.subtract(component, calendar: Calendar.current) }
static func -= (date: inout Date, component: Date.Component) {
guard let newDate = date.subtract(component, calendar: Calendar.current) else { return }
date = newDate
}
}
Usage
var currentDate = Date()
let date1 = Date(bySubtracting: (30, .day), from: currentDate)
let date2 = Date().subtract((30, .day))
let date3 = Date().subtract([(1, .minute), (2, .hour), (3, .day), (4, .month)])
let component = Date.Component(value: 1, type: .day)
let date4 = Date.beforeNow(difference: component)
let date5 = Date.beforeNow(difference: (1, .minute), (2, .hour), (3, .day), (4, .month))
let date6 = Date.beforeNow(difference: [(1, .minute), (2, .hour), (3, .day), (4, .month)])
let date7 = currentDate - (1, .day)
currentDate -= Date.Component(value: 1, type: .day)
More

- 24,482
- 9
- 132
- 127
let now = Date()
let nowMinusTwoAndAHalfHours = now - 2.5*60*60
print(now)
print(nowMinusTwoAndAHalfHours)

- 252
- 3
- 3