Search code examples
iosswiftcore-datansdate

Check if date is in coming month


I'm setting a date to a certain birthdayTextField like so

@objc func birthdayDatePickerValueChanged(sender: UIDatePicker) {
    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    formatter.timeStyle = .none
    birthdayTextField.text = formatter.string(from: sender.date)

}

Now this textfield value is stored in coredata in a string attribute. There can be many such birthday dates stored in coredata. Now when I fetch these dates from the database, I want to show in a tableview only those dates which come in the following month.

How can it be achieved...?


Solution

  • This is a solution using the powerful date math abilities of Calendar together with DateComponents in a Date extension.

    • It calculates the first day of next month with nextDate(after:matching:matchingPolicy:) looking for day == 1
    • It compares the given date with the first date of next month to the month granularity with compare(:to:toGranularity:).

    extension Date {
        func isDateInNextMonth() -> Bool {
            let calendar = Calendar.current
            let nextMonth = calendar.nextDate(after: Date(), matching: DateComponents(day:1), matchingPolicy: .nextTime)!
            return calendar.compare(self, to: nextMonth, toGranularity: .month) == .orderedSame
       }
    }
    

    Use it simply in your method

    sender.date.isDateInNextMonth()
    

    Or – more versatile – according to the other isDateIn... methods as extension of Calendar

    extension Calendar {
        func isDateInNextMonth(_ date : Date) -> Bool {
            let nextMonth = self.nextDate(after: Date(), matching: DateComponents(day:1), matchingPolicy: .nextTime)!
            return self.compare(date, to: nextMonth, toGranularity: .month) == .orderedSame
        }
    }
    

    and use it

    Calendar.current.isDateInNextMonth(sender.date)
    

    Edit:

    If you want to check if the date is in the next 30 days it's still easier

    extension Calendar {
        func isDateInNextThirtyDays(_ date : Date) -> Bool {
            return self.dateComponents([.month], from: Date(), to:date).month! < 1
        }
    }