Search code examples
swiftnsdatenscalendar

Testing for Anniversary Date using NSDate/NSCalendar


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
    //      }

}

Solution

  • 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)!")
        }
    }