13

Im new at swift programming and i havent been able successfully find code to find difference between two dates in terms of years , months and days. I tried the following code but it didnt work

let form = NSDateComponentsFormatter()
form.maximumUnitCount = 2
form.unitsStyle = .Full
let s = form.stringFromTimeInterval( date2.timeIntervalSinceReferenceDate - date1.timeIntervalSinceReferenceDate)

Input

Date1 = "12/March/2015"

Date2 = "1/June/2015"

Output : x years y months z days

Please advice

Imanou Petit
  • 89,880
  • 29
  • 256
  • 218
alanvabraham
  • 779
  • 2
  • 14
  • 25
  • 4
    *"this is not working to my needs"* is useless as a problem description. Please show your exact input data, the expected output and the actual output. – Martin R Nov 18 '15 at 12:36
  • And stringFromTimeInterval is useless because it throws away valuable information. 29 days is sometimes one month plus one day, sometimes one month, sometimes just 29 days. – gnasher729 Nov 18 '15 at 12:38
  • @vikingosegundo: The referenced thread does not explain how **NSDateComponentsFormatter** is properly used, so I would not consider that as a duplicate. – Martin R Nov 18 '15 at 12:52
  • @MartinR: you might be right, but actually the title and the question body do not match. Getting the right components and formatiing them are anyway 2 different and independent thgings. – vikingosegundo Nov 18 '15 at 12:53

6 Answers6

18

We can use this function in Swift 2.0

func yearsBetweenDate(startDate: NSDate, endDate: NSDate) -> Int
{
    let calendar = NSCalendar.currentCalendar()

    let components = calendar.components([.Year], fromDate: startDate, toDate: endDate, options: [])

    return components.year
}

You can return anything like I returned year in this function. This will return number of years between the two dates.
You can just write months,days etc in order to find the difference between the two dates in months and days respectively.

Edit

Swift 3.0 and Above

func yearsBetweenDate(startDate: Date, endDate: Date) -> Int {

    let calendar = Calendar.current

    let components = calendar.dateComponents([.year], from: startDate, to: endDate)

    return components.year!
}
Nosov Pavel
  • 1,571
  • 1
  • 18
  • 34
Rajan Maheshwari
  • 14,465
  • 6
  • 64
  • 98
9

If you need the difference (in years, months, days) numerically then compute NSDateComponents as in Swift days between two NSDates or Rajan's answer.

If you need the difference as a (localized) string to present it to the user, then use NSDateComponentsFormatter like this

let form = NSDateComponentsFormatter()
form.maximumUnitCount = 2
form.unitsStyle = .Full
form.allowedUnits = [.Year, .Month, .Day]
let s = form.stringFromDate(date1, toDate: date2)

As already mentioned in the comments, computing the difference from the pure time interval between the dates cannot give correct results because most information about the dates is lost.

Update for Swift 3:

let form = DateComponentsFormatter()
form.maximumUnitCount = 2
form.unitsStyle = .full
form.allowedUnits = [.year, .month, .day]
let s = form.string(from: date1, to: date2)
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Thank you for the answers. One final query if i needs to separate the numerals of year month and day from the string is there any function inbuilt or i have to go through the string one by one. For eg : s = " 1 year 2 months 3 days" whats the easiest way to extract 1 ,2 and 3 – alanvabraham Nov 18 '15 at 13:18
  • @alanvabraham: As I said, if you need year/month/day numerically then you better use NSDateComponents as in http://stackoverflow.com/questions/24723431/swift-days-between-two-nsdates or Rajan's answer, and not a NSDateComponentsFormatter. – Martin R Nov 18 '15 at 13:19
  • in the answer above s returns for eg : 1 year 2 months 3 days . i like to know if there is any function to extract these numbers from string. I understand the allowed units function would return the individual units but the answer is not the same in both cases. – alanvabraham Nov 23 '15 at 13:56
3

With Swift 5 and iOS 12, you can use one of the 3 solutions below in order to calculate the difference (in years, months, days) between two dates.


#1. Using Calendar's dateComponents(_:from:to:) method

Calendar has a method called dateComponents(_:from:to:). dateComponents(_:from:to:) has the following declaration:

func dateComponents(_ components: Set<Calendar.Component>, from start: DateComponents, to end: DateComponents) -> DateComponents

Returns the difference between two dates specified as DateComponents.

The Playground example below show how to use dateComponents(_:from:to:) in order to compute the difference between two dates:

import Foundation

let calendar = Calendar.current
let startComponents = DateComponents(year: 2010, month: 11, day: 22)
let endComponents = DateComponents(year: 2015, month: 5, day: 1)

let dateComponents = calendar.dateComponents([.year, .month, .day], from: startComponents, to: endComponents)
print(dateComponents) // prints: year: 4 month: 5 day: 9 isLeapMonth: false

#2. Using Calendar's dateComponents(_:from:to:) method

Calendar has a method called dateComponents(_:from:to:). dateComponents(_:from:to:) has the following declaration:

func dateComponents(_ components: Set<Calendar.Component>, from start: Date, to end: Date) -> DateComponents

Returns the difference between two dates.

The Playground example below show how to use dateComponents(_:from:to:) in order to compute the difference between two dates:

import Foundation

let calendar = Calendar.current
let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))!
let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))!

let dateComponents = calendar.dateComponents([.year, .month, .day], from: startDate, to: endDate)
print(dateComponents) // prints: year: 4 month: 5 day: 9 isLeapMonth: false

#3. Using DateComponentsFormatter's string(from:to:) method

DateComponentsFormatter has a method called string(from:to:). string(from:to:) has the following declaration:

func string(from startDate: Date, to endDate: Date) -> String?

Returns a formatted string based on the time difference between two dates.

The Playground example below show how to use string(from:to:) in order to compute the difference between two dates:

import Foundation

let calendar = Calendar.current
let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))!
let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))!

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.allowedUnits = [.year, .month, .day]
let string = formatter.string(from: startDate, to: endDate)!
print(string) // prints: 4 years, 5 months, 9 days
Imanou Petit
  • 89,880
  • 29
  • 256
  • 218
0

Try this one

func calculateDiffInTwoDate (date1: NSDate, date2: NSDate) -> NSInteger {

        //var userAge : NSInteger = 0
        let calendar : NSCalendar = NSCalendar.currentCalendar()
        let unitFlags : NSCalendarUnit = [ .Year , .Month, .Day]
        let dateComponentNow : NSDateComponents = calendar.components(unitFlags, fromDate: date2)
        let dateComponentBirth : NSDateComponents = calendar.components(unitFlags, fromDate: date1)

        if ( (dateComponentNow.month < dateComponentBirth.month) ||
            ((dateComponentNow.month == dateComponentBirth.month) && (dateComponentNow.day < dateComponentBirth.day))
            )
        {
            return dateComponentNow.year - dateComponentBirth.year - 1
        }
        else {
            return dateComponentNow.year - dateComponentBirth.year
        }
    }

By This you can get diff between two dates in Years

Tejas Ardeshna
  • 4,343
  • 2
  • 20
  • 39
  • Why are you making it so hard? NSCalendar can calculate the components from one date to another date. components:fromDate:toDate:options:. – gnasher729 Nov 18 '15 at 12:43
0

Why don't you use the inbuild method to find the difference between 2 dates in seconds, and then write a method to convert seconds in terms of years, months and days.

let diff = date1.timeIntervalSinceDate(date2)
Nishant
  • 12,529
  • 9
  • 59
  • 94
  • See my comment above - when you calculate the time interval in seconds, you are losing information. Months are supposed to have different lengths. So do days. So do years. – gnasher729 Nov 18 '15 at 12:44
  • Then u should use Rajan's answer below. – Nishant Nov 18 '15 at 12:45
0
    //Assigning Dates
    let StartDate = datePicker.date
    let currentDate = Date()

    //Finding Difference of Dates
    let components = Set<Calendar.Component>([.day, .month, .year])
    let differenceOfDate = Calendar.current.dateComponents(components, from: 
     StartDate, to: currentDate)

    Print(differenceOfDate)