Aaron - 1 year ago 106

Swift Question

I'm building a birthday reminder app. I want the user to be able to see how many days it is until somebody's next birthday.

Let's say I have an

`NSDate()`

`2015-06-30 07:21:47 +0000`

And the

`NSDate`

`1985-08-29 12:00:00 +0000`

How would I get the number of days until the next birthday? I've used something like this which gives a negative number of days since the date's actual beginning (which are in the thousands with birthdates). Then with that I would add 365 to the numerical difference until it was positive but it still returns a wonky number. I'm assuming due to leap years or something.

Is there a method to this I can implement? Somehow equalize the year components so that it's always comparing from the next birthday and not the original birthdate?

Edit:

Here is the function I am using:

`func daysBetween(date1: NSDate, date2: NSDate) -> Int {`

var calendar: NSCalendar = NSCalendar.currentCalendar()

let date1 = calendar.startOfDayForDate(date1)

let date2 = calendar.startOfDayForDate(date2)

let flags = NSCalendarUnit.CalendarUnitDay

let components = calendar.components(flags, fromDate: date1, toDate: date2, options: nil)

return components.day

}

With the example dates I posted I would use it like this:

`// sampleDate = 1985-08-29 12:00:00 +0000`

daysBetween(sampleDate, date2: NSDate())

// --> 10897

Whether positive or negative, the number is in the thousands. I'm looking to equalize that into number of days to the next calendar birthday.

Recommended for you: Get network issues from **WhatsUp Gold**. **Not end users.**

Answer Source

What you need is to compute the *next occurrence* of the (day and month
component of the) birthday after today:

```
let cal = NSCalendar.currentCalendar()
let today = cal.startOfDayForDate(NSDate())
let dayAndMonth = cal.components(.CalendarUnitDay | .CalendarUnitMonth,
fromDate: birthday)
let nextBirthDay = cal.nextDateAfterDate(today,
matchingComponents: dayAndMonth,
options: .MatchNextTimePreservingSmallerUnits)!
```

Remarks:

The purpose of the

`MatchNextTimePreservingSmallerUnits`

option is that if the birthday is on February 29 (in the Gregorian calendar), its next occurrence will be computed as March 1 if the year is not a leap year.You might need to check first if the birthday is

*today*, as it seems that`nextDateAfterDate()`

would return the*next*birthday in that case.

Then you can compute the difference in days as usual:

```
let diff = cal.components(.CalendarUnitDay,
fromDate: today,
toDate: nextBirthDay,
options: nil)
println(diff.day)
```

**Update for Swift 2.2 (Xcode 7.3):**

```
let cal = NSCalendar.currentCalendar()
let today = cal.startOfDayForDate(NSDate())
let dayAndMonth = cal.components([.Day, .Month],
fromDate: birthday)
let nextBirthDay = cal.nextDateAfterDate(today,
matchingComponents: dayAndMonth,
options: .MatchNextTimePreservingSmallerUnits)!
let diff = cal.components(.Day,
fromDate: today,
toDate: nextBirthDay,
options: [])
print(diff.day)
```

**Update for Swift 3 (Xcode 8 beta):**

```
let cal = Calendar.current()
let today = cal.startOfDay(for: Date())
let dayAndMonth = cal.components([.day, .month], from: birthday)
let nextBirthDay = cal.nextDate(after: today, matching: dayAndMonth,
options: .matchNextTimePreservingSmallerUnits)!
let diff = cal.components(.day, from: today, to: nextBirthDay)
print(diff.day!)
```

Recommended from our users: **Dynamic Network Monitoring from WhatsUp Gold from IPSwitch**. ** Free Download**