Implementing Weekday Calendar Reminders with Holiday Filtering on iOS
This article demonstrates how to create recurring iOS calendar reminders for Monday‑to‑Friday workdays, filter out Chinese statutory holidays using an external holiday‑cn JSON source, and handle make‑up workdays, providing complete Swift code and step‑by‑step explanations.
Background
The author needed a reliable alarm that skips Chinese statutory holidays on iOS, but iOS does not allow third‑party apps to add alarms directly to the Clock app, nor does it provide built‑in holiday detection. Using Calendar reminders instead of alarms offers a viable solution.
Implementation
Step 1 – Create a Monday‑to‑Friday recurring event
iOS EventKit provides EKRecurrenceRule to define recurrence patterns. The rule is built to repeat weekly on Monday through Friday.
let monday = EKRecurrenceDayOfWeek(.monday)
let tuesday = EKRecurrenceDayOfWeek(.tuesday)
let wednesday = EKRecurrenceDayOfWeek(.wednesday)
let thursday = EKRecurrenceDayOfWeek(.thursday)
let friday = EKRecurrenceDayOfWeek(.friday)
let rule = EKRecurrenceRule(recurrenceWith: .weekly,
interval: 1,
daysOfTheWeek: [monday, tuesday, wednesday, thursday, friday],
daysOfTheMonth: nil,
monthsOfTheYear: nil,
weeksOfTheYear: nil,
daysOfTheYear: nil,
setPositions: nil,
end: nil)Permission handling, calendar creation, and event generation are encapsulated in helper functions:
lazy fileprivate var store = EKEventStore()
func requestEventAuth(_ callback: ((Bool) -> Void)?) {
store.requestAccess(to: .event) { granted, _ in callback?(granted) }
}
func createNewCalendar() { /* create a dedicated calendar */ }
func generateEvent(_ title: String?, location: String?, notes: String?, timeStr: String?) -> EKEvent { /* set title, dates, alarm, recurrence */ }
func addEvent(title: String?, location: String?, notes: String?, timeStr: String, eventKey: String) { /* request auth, create calendar, avoid duplicates, save */ }Step 2 – Add statutory‑holiday logic
The holiday‑cn JSON provides an array of objects with name , date and isOffDay . The app downloads this file, parses it, and for each day decides whether to delete an existing reminder (if it is a holiday) or add a make‑up reminder (if it is a workday on a weekend).
func filterHolidayInfo(with title: String?, location: String?, notes: String?, timeStr: String, eventKey: String) {
guard let url = URL(string: "https://natescarlet.coding.net/p/github/d/holiday-cn/git/raw/master/2021.json") else { return }
let task = URLSession.shared.dataTask(with: url) { data, _, _ in
guard let data = data else { return }
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let days = json["days"] as? [[String: Any]] {
self.handleHolidayInfo(with: days, title: title, location: location, notes: notes, timeStr: timeStr, eventKey: eventKey)
}
} catch { print(error) }
}
task.resume()
}
func handleHolidayInfo(with days: [[String: Any]], title: String?, location: String?, notes: String?, timeStr: String, eventKey: String) {
for day in days {
guard let dayStr = day["date"] as? String,
let date = Date.date(from: dayStr, formatterStr: "yyyy-MM-dd"),
let isOffDay = day["isOffDay"] as? Bool else { continue }
if date.timeIntervalSinceNow < 0 { continue }
if let existing = eventExist(on: date, eventKey: eventKey) {
if isOffDay { try? store.remove(existing, span: .thisEvent) }
} else if !isOffDay {
// add make‑up event
let timePart = timeStr.components(separatedBy: " ").last ?? "00:00:00"
let targetStr = "\(dayStr) \(timePart)"
let event = generateEvent(title, location: location, notes: notes, timeStr: targetStr)
try? store.save(event, span: .thisEvent)
}
}
}Utility functions eventExist and eventExist check for existing events in the custom calendar to avoid duplicates.
Result
After running the code, the calendar shows reminders on every weekday except official holidays, and additional reminders are created for make‑up workdays (e.g., 2021‑09‑18, 2021‑09‑26, 2021‑10‑09). Screenshots confirm the expected behavior.
Conclusion
The approach combines EventKit recurrence rules with dynamic holiday data, offering a flexible way to manage work‑day reminders on iOS. Future improvements could include versioned holiday data from a private server to automatically refresh the calendar when the holiday list changes.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.