Getting the difference between two Dates (months/days/hours/minutes/seconds) in Swift
Xcode 8.3 • Swift 3.1 or later
You can use Calendar to help you create an extension to do your date calculations as follow:
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))y" }
if months(from: date) > 0 { return "\(months(from: date))M" }
if weeks(from: date) > 0 { return "\(weeks(from: date))w" }
if days(from: date) > 0 { return "\(days(from: date))d" }
if hours(from: date) > 0 { return "\(hours(from: date))h" }
if minutes(from: date) > 0 { return "\(minutes(from: date))m" }
if seconds(from: date) > 0 { return "\(seconds(from: date))s" }
return ""
}
}
Using Date Components Formatter
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.allowedUnits = [.second, .minute, .hour, .day, .weekOfMonth, .month, .year]
dateComponentsFormatter.maximumUnitCount = 1
dateComponentsFormatter.unitsStyle = .full
dateComponentsFormatter.string(from: Date(), to: Date(timeIntervalSinceNow: 4000000)) // "1 month"
let date1 = DateComponents(calendar: .current, year: 2014, month: 11, day: 28, hour: 5, minute: 9).date!
let date2 = DateComponents(calendar: .current, year: 2015, month: 8, day: 28, hour: 5, minute: 9).date!
let years = date2.years(from: date1) // 0
let months = date2.months(from: date1) // 9
let weeks = date2.weeks(from: date1) // 39
let days = date2.days(from: date1) // 273
let hours = date2.hours(from: date1) // 6,553
let minutes = date2.minutes(from: date1) // 393,180
let seconds = date2.seconds(from: date1) // 23,590,800
let timeOffset = date2.offset(from: date1) // "9M"
let date3 = DateComponents(calendar: .current, year: 2014, month: 11, day: 28, hour: 5, minute: 9).date!
let date4 = DateComponents(calendar: .current, year: 2015, month: 11, day: 28, hour: 5, minute: 9).date!
let timeOffset2 = date4.offset(from: date3) // "1y"
let date5 = DateComponents(calendar: .current, year: 2017, month: 4, day: 28).date!
let now = Date()
let timeOffset3 = now.offset(from: date5) // "1w"
Calculating the difference between two dates in Swift
I ended up creating a custom operator for Date
:
extension Date {
static func - (lhs: Date, rhs: Date) -> TimeInterval {
return lhs.timeIntervalSinceReferenceDate - rhs.timeIntervalSinceReferenceDate
}
}
With this operator I can now compute the difference between two dates on a more abstract level without caring about timeIntervalSinceReferenceDate
or what exactly the reference date is – and without losing precision, for example:
let delta = toDate - fromDate
Obviously, I didn't change much, but for me it's a lot more readable and consequent: Swift has the +
operator already implemented for a Date
and a TimeInterval
:
/// Returns a `Date` with a specified amount of time added to it.
public static func + (lhs: Date, rhs: TimeInterval) -> Date
So it's already supporting
Date + TimeInterval = Date
Consequently, it should also support
Date - Date = TimeInterval
in my opinion and that's what I added with the simple implementation of the -
operator. Now I can simply write the example function exactly as mentioned in my question:
func computeNewDate(from fromDate: Date, to toDate: Date) -> Date
let delta = toDate - fromDate // `Date` - `Date` = `TimeInterval`
let today = Date()
if delta < 0 {
return today
} else {
return today + delta // `Date` + `TimeInterval` = `Date`
}
}
It might very well be that this has some downsides that I'm not aware of at this moment and I'd love to hear your thoughts on this.
Getting the difference in two dates - Swift
Change all of your NSDate
to Date
, then replace your requestedComponent
with this:
let requestedComponent: Set<Calendar.Component> = [ .month, .day, .hour, .minute, .second]
Your difference will be:
let timeDifference = userCalendar.dateComponents(requestedComponent, from: startTime, to: endTime!)
FYI: Your dateFormatter
doesn't work with this "25/12/16 00:00:00"
here is your whole class in correct form:
class ViewController: UIViewController {
@IBOutlet weak var dateLabelOutlet: UILabel!
let currentDate = Date()
let dateFormatter = DateFormatter()
let userCalendar = Calendar.current
let requestedComponent: Set<Calendar.Component> = [.month,.day,.hour,.minute,.second]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func printTime() {
dateFormatter.dateFormat = "dd/MM/yy hh:mm:ss"
let startTime = Date()
let endTime = dateFormatter.date(from: "25/12/16 00:00:00")
let timeDifference = userCalendar.dateComponents(requestedComponent, from: startTime, to: endTime!)
dateLabelOutlet.text = "\(timeDifference.month) Months \(timeDifference.day) Days \(timeDifference.minute) Minutes \(timeDifference.second) Seconds"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Calculating the number of days between two dates in swift
It has to do with the order that you're creating your variables and comparing them.
The first thing you do is create today
. Then, you create twoWeeksFromNow
, based on a new Date()
that will be slightly further in the future than today
was. On my machine, in a playground, the second date is about 300 microseconds further in the future than the first.
Then, for numDaysWithDate
, you compare twoWeeksFromNow
to another new Date()
, even more slightly in the future. So, your time frame is very slightly less than 2 full weeks, giving you 13 days.
But, for numDaysWithToday
, you compare twoWeeksFromNow
with the original today
, which was created before twoWeeksFromNow
was, making it slightly longer than 2 weeks, giving you 14 days.
If you change the order of the the today
and twoWeeksFromNow
declarations, you can see a different result:
var twoWeeksFromNow: Date = Calendar.current.date(byAdding: .day,
value: 14, to: Date())!
var today = Date()
Now, because today
was created slightly later than the date that twoWeeksFromNow
was created from, both results are 13.
Swift - Find Difference Between Upcoming Time and Current Time
once you have your dates from the strings, you coud do something like this using component:
EDIT, using Alexander suggestion:
struct ContentView: View {
@State var timediff = ""
var body: some View {
Text(timediff)
.onAppear {
let RFC3339DateFormatter = DateFormatter()
RFC3339DateFormatter.locale = Locale(identifier: "en_US_POSIX")
RFC3339DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
RFC3339DateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let string1 = "1996-12-19T16:39:57-08:00"
let date1 = RFC3339DateFormatter.date(from: string1)
let string2 = "1996-12-19T13:19:27-08:00"
let date2 = RFC3339DateFormatter.date(from: string2)
if let d1 = date1, let d2 = date2 {
let result = Calendar.current.dateComponents([.hour, .minute], from: d1, to: d2)
timediff = result.description
}
}
}
Difference between 2 dates in weeks and days using swift 3 and xcode 8
You can use Calendar
's dateComponents(_:from:to:)
to find the difference between 2 dates to your desired units.
Example:
let dateRangeStart = Date()
let dateRangeEnd = Date().addingTimeInterval(12345678)
let components = Calendar.current.dateComponents([.weekOfYear, .month], from: dateRangeStart, to: dateRangeEnd)
print(dateRangeStart)
print(dateRangeEnd)
print("difference is \(components.month ?? 0) months and \(components.weekOfYear ?? 0) weeks")
> 2017-02-17 10:05:19 +0000
> 2017-07-10 07:26:37 +0000
> difference is 4 months and 3 weeks
let months = components.month ?? 0
let weeks = components.weekOfYear ?? 0
Related Topics
Ios: How to Get a Proper Month Name from a Number
Why Does Viewwillappear Not Get Called When an App Comes Back from the Background
How to Create a Button Programmatically
How to Play Video With Avplayerviewcontroller (Avkit) in Swift
Check If My App Has a New Version on Appstore
How to Completely Uninstall Xcode and Clear All Settings
How to Hide Keyboard When Using Swiftui
How to Hide Google Maps Location Dot
How to Display 3 Cells Per Row in Uicollectionview
Iphone/Ipad: How to Make Uitextfield Readonly (But Not Disabled)
Get Current Scroll Position of Scrollview in React Native
Nsdictionary to Nsdata and Nsdata to Nsdictionary in Swift
Uiimageview - How to Get the File Name of the Image Assigned
Xcode 10.2.1 Command Phasescriptexecution Failed With a Nonzero Exit Code
How to Download Multiple Files Sequentially Using Nsurlsession Downloadtask in Swift