34

I am trying to calculate the difference between 2 dates (one is the current date and the other from datepicker) in weeks and days then displaying the result on a label, that's what i have done so far, i appreciate the help of more experienced developers here!

let EDD = datePicker.date
let now = NSDate()

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .short
formatter.allowedUnits = [.day]
formatter.maximumUnitCount = 2   

let string = formatter.string (from: now as Date, to: EDD)

label.text = string
Ashley Mills
  • 41,127
  • 14
  • 115
  • 144
FormulaOne
  • 339
  • 1
  • 3
  • 7
  • Hey FormulaOne.... Please See this answer http://stackoverflow.com/questions/27182023/getting-the-difference-between-two-nsdates-in-months-days-hours-minutes-seconds – shafi Feb 17 '17 at 10:03
  • It would improve the question if you said how your current code (which is fine as far as it goes) is falling short of your desired outcome. – JeremyP Feb 17 '17 at 11:12
  • Makes sense as it would save you time to find me an answer, next time! :) – FormulaOne Feb 17 '17 at 11:35

4 Answers4

59

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
Ashley Mills
  • 41,127
  • 14
  • 115
  • 144
  • Thanks for your help, the first solution worked beautifully for me though :) – FormulaOne Feb 17 '17 at 11:19
  • Right, what i really wanted was the difference between the dates in days (or weeks) then i can use that difference to make a calculation, what i am getting from your solution is a string that i can't make any calculations on, Thanks – FormulaOne Feb 17 '17 at 12:09
  • If you look how the string is constructed, you'll see the `components.month` and `components.weekOfYear` these are `Int` values – Ashley Mills Feb 17 '17 at 12:10
  • @FormulaOne I'm always happy to accept an upvote by way of thanks! ;) – Ashley Mills Feb 18 '17 at 21:53
  • don't even know how to do that! – FormulaOne Feb 19 '17 at 09:33
  • If you see an answer you like, click the up arrow at the top left of that answer. If someone answers your question, click on the checkmark – Ashley Mills Feb 19 '17 at 09:35
12

You are close. Just add .weekOfMonth (meaning "quantity of weeks" according to the API documentation) to the allowed units. Example:

let now = Date()
let endDate = now.addingTimeInterval(24 * 3600 * 17)

let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.day, .weekOfMonth]
formatter.unitsStyle = .full
let string = formatter.string(from: now, to: endDate)!

print(string) // 2 weeks, 3 days

Setting maximumUnitCount = 2 is not necessary because there are only two allowed units.

Martin R
  • 488,667
  • 78
  • 1,132
  • 1,248
  • Right, what i really wanted was the difference between the dates in days (or weeks) then i can use that difference to make a calculation, what i am getting from your solution is a string that i can't make any calculations on, Thanks – FormulaOne Feb 17 '17 at 12:06
  • 1
    @FormulaOne: Well that wasn't apparent from your question. You said *"... then displaying the result on a label... "* which means that you want a string. – If you need the difference as numbers then use DateComponents as suggested in Ashley's answer. – Martin R Feb 17 '17 at 12:08
5

Swift 4

testing using Xcode Version 9.2

  • combining the above two answers that helps me

Use the following method to get the string by the difference between two dates the idea is to localize the words weeks/ days /minutes by the format.

func getTimeComponentString(olderDate older: Date,newerDate newer: Date) -> (String?)  {
    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .full

    let componentsLeftTime = Calendar.current.dateComponents([.minute , .hour , .day,.month, .weekOfMonth,.year], from: older, to: newer)

    let year = componentsLeftTime.year ?? 0
    if  year > 0 {
        formatter.allowedUnits = [.year]
        return formatter.string(from: older, to: newer)
    }


    let month = componentsLeftTime.month ?? 0
    if  month > 0 {
        formatter.allowedUnits = [.month]
        return formatter.string(from: older, to: newer)
    }

    let weekOfMonth = componentsLeftTime.weekOfMonth ?? 0
    if  weekOfMonth > 0 {
        formatter.allowedUnits = [.weekOfMonth]
        return formatter.string(from: older, to: newer)
    }

    let day = componentsLeftTime.day ?? 0
    if  day > 0 {
        formatter.allowedUnits = [.day]
        return formatter.string(from: older, to: newer)
    }

    let hour = componentsLeftTime.hour ?? 0
    if  hour > 0 {
        formatter.allowedUnits = [.hour]
        return formatter.string(from: older, to: newer)
    }

    let minute = componentsLeftTime.minute ?? 0
    if  minute > 0 {
        formatter.allowedUnits = [.minute]
        return formatter.string(from: older, to: newer) ?? ""
    }

    return nil
}

Here is how you can use

    let nowDate = Date()
    let endDate = Date().addingTimeInterval(12345678)

    let string =  String.getTimeComponentString(olderDate: nowDate, newerDate: endDate)!
    print(nowDate)
    print(endDate)
    print(string)
  • Output

  • 2018-03-08 08:11:22 +0000
  • 2018-07-29 05:32:41 +0000
  • 4 months
Amr Angry
  • 3,208
  • 39
  • 35
2

Swift 4,5

You can find date different in weeks with this one line code.

let totalWeeks = Calendar.current.dateComponents([.weekOfMonth], from: Date(), to: endDate).weekOfMonth!

//for totalDays
let totalDays = Calendar.current.dateComponents([.day], from: Date(), to: endDate).day!