0

I'm trying to figure out how to determine whether today is the anniversary of an NSCalendar item. Everything I've found compares a specific date's month, day, year to another specific month, day, and year. The granularity works against me, as the first thing it compares is the year.

Here's what I've got so far. I've read the documentation, but I'm missing something (basic). What is it?

// get the current date
let calendar = NSCalendar.currentCalendar()
var dateComponents = calendar.components([.Month, .Day], fromDate: NSDate())

let today = calendar.dateFromComponents(dateComponents)

var birthDates = [NSDate]()

let tomsBirthday = calendar.dateWithEra(1, year: 1964, month: 9, day: 3, hour: 0, minute: 0, second: 0, nanosecond: 0)
birthDates.append(tomsBirthday!)

let dicksBirthday = calendar.dateWithEra(1, year: 1952, month: 4, day: 5, hour: 0, minute: 0, second: 0, nanosecond: 0)
birthDates.append(dicksBirthday!)

let harrysBirthday = calendar.dateWithEra(1, year: 2015, month: 10, day: 27, hour: 0, minute: 0, second: 0, nanosecond: 0)
birthDates.append(harrysBirthday!)

for birthday in birthDates {
    // compare the month and day to today's month and day
    // if birthday month == today's month {
    //      if birthday day == today's day {
    //             do something
    //      }

}
Adrian
  • 16,233
  • 18
  • 112
  • 180

1 Answers1

2

To make the date comparison, while treating February 29 as March 1 in non-leap years, you need to use the month and day components of the person's birthday to construct an NSDate in the current year.

Also, don't use midnight as time when constructing an NSDate for comparing dates. Some days don't have a midnight in some time zones. Use noon instead.

struct Person {
    let name: String
    let birthYear: Int
    let birthMonth: Int
    let birthDay: Int
}

let people = [
    Person(name: "Tom", birthYear: 1964, birthMonth: 9, birthDay: 3),
    Person(name: "Dick", birthYear: 1952, birthMonth: 4, birthDay: 5),
    Person(name: "Harry", birthYear: 2015, birthMonth: 10, birthDay: 28)
]

let calendar = NSCalendar.autoupdatingCurrentCalendar()

let todayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate: NSDate())
todayComponents.hour = 12
let todayNoon = calendar.dateFromComponents(todayComponents)

for person in people {
    let components = todayComponents.copy() as! NSDateComponents
    // DON'T copy person.birthYear
    components.month = person.birthMonth
    components.day = person.birthDay
    let birthdayNoon = calendar.dateFromComponents(components)
    if todayNoon == birthdayNoon {
        print("Happy birthday, \(person.name)!")
    }
}
Community
  • 1
  • 1
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • You could change the last for statement to be for birthDay in birthDays.filter({$0 == today}) and remove the if check – totiDev Oct 27 '15 at 23:06
  • Awesome! I thought I had to create the birthday, then break it apart to compare it. This is much easier. Thank you! – Adrian Oct 28 '15 at 01:03
  • 1
    There is one problem (I think). If the person's birthday is on Feb 29 and the current year is *not* a leap year, then the comparison with today's date should yield true on March 1. Therefore it may be better to convert the date components (together with the current year) to an NSDate and check that with `isDateInToday()`. – Martin R Oct 28 '15 at 06:35
  • I've revised my answer. – rob mayoff Oct 28 '15 at 17:26