Search code examples
cocoalocalensdateformatternscalendar

How to get weekends vs weekdays in Cocoa?


What is the correct calendar-agnostic way (in either iOS or OS X) to get standard business days of the week (e.g. weekdays) versus non-working days of the week? This is taking into account that some parts of the world doesn't follow the Monday through Friday working day routine. E.g. the UAE and some parts of Malaysia works from Sunday through Thursday.

I'm looking to emulate iOS' built-in Alarm application in which if I select a repeating day of Monday through Friday, it will say that my alarm repeats "Weekdays" whereas for alarms that fires on Saturday and Sunday says "Weekends". However, I'd like my app to also work correctly in other parts of the world that doesn't follow the western world's work week.

I've been toying around with NSCalendar's isDateInWeekend function with various other calendars and haven't been able to find a good method to determine weekday vs weekend. Here's a snippet from a Swift playground that I got so far:

import UIKit

let arabicLocale = NSLocale(localeIdentifier: "en_AR")
let islamicTabularCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierIslamicTabular)
islamicTabularCalendar?.locale = arabicLocale
let islamicTabularFormatter = NSDateFormatter()
islamicTabularFormatter.calendar = islamicTabularCalendar
islamicTabularFormatter.dateStyle = NSDateFormatterStyle.FullStyle

let gregorianCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
gregorianCalendar?.locale = arabicLocale
let gregorianFormatter = NSDateFormatter()
gregorianFormatter.calendar = gregorianCalendar
gregorianFormatter.dateStyle = NSDateFormatterStyle.FullStyle

let monday = NSDateComponents()
monday.weekday = 2
monday.weekOfMonth = 0
let friday = NSDateComponents()
friday.weekday = 6
friday.weekOfMonth = 0

let mondayDate = islamicTabularCalendar?.dateFromComponents(monday)
gregorianFormatter.stringFromDate(mondayDate!)          // "Monday, July 8, 622"
islamicTabularFormatter.stringFromDate(mondayDate!)     // "Monday, Dhuʻl-Hijjah 20, 0 AH"
islamicTabularCalendar?.isDateInWeekend(mondayDate!)    // false

let fridayDate = islamicTabularCalendar?.dateFromComponents(friday)
gregorianFormatter.stringFromDate(fridayDate!)          // Friday, July 12, 622
islamicTabularFormatter.stringFromDate(fridayDate!)     // Friday, Dhuʻl-Hijjah 24, 0 AH
islamicTabularCalendar?.isDateInWeekend(fridayDate!)    // false

What I'm looking for is something that returns false for Fridays in parts of the world that practices Monday-Friday working days but returns true for UAE and the like.


Solution

  • I finally got it. The mistake was in the locale identifier which should be en_AE instead of en_AR

    import UIKit
    
    let arabicLocale = NSLocale(localeIdentifier: "en_AE")
    let islamicTabularCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierIslamicTabular)
    islamicTabularCalendar?.locale = arabicLocale
    let islamicTabularFormatter = NSDateFormatter()
    islamicTabularFormatter.calendar = islamicTabularCalendar
    islamicTabularFormatter.dateStyle = NSDateFormatterStyle.FullStyle
    
    let gregorianCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
    gregorianCalendar?.locale = arabicLocale
    let gregorianFormatter = NSDateFormatter()
    gregorianFormatter.calendar = gregorianCalendar
    gregorianFormatter.dateStyle = NSDateFormatterStyle.FullStyle
    
    let monday = NSDateComponents()
    monday.weekday = 2
    monday.weekOfMonth = 0
    let friday = NSDateComponents()
    friday.weekday = 6
    friday.weekOfMonth = 0
    
    let mondayDate = islamicTabularCalendar?.dateFromComponents(monday)
    gregorianFormatter.stringFromDate(mondayDate!)          // "Monday, July 8, 622"
    islamicTabularFormatter.stringFromDate(mondayDate!)     // "Monday, Dhuʻl-Hijjah 20, 0 AH"
    islamicTabularCalendar?.isDateInWeekend(mondayDate!)    // false
    gregorianCalendar?.isDateInWeekend(mondayDate!)         // false
    
    let fridayDate = islamicTabularCalendar?.dateFromComponents(friday)
    gregorianFormatter.stringFromDate(fridayDate!)          // Friday, July 12, 622
    islamicTabularFormatter.stringFromDate(fridayDate!)     // Friday, Dhuʻl-Hijjah 24, 0 AH
    islamicTabularCalendar?.isDateInWeekend(fridayDate!)    // true
    gregorianCalendar?.isDateInWeekend(fridayDate!)         // false