Disabling all other days in calendar view

3k views Asked by At

I have a form in which the user will select days and then select a date from calendar view..

for example: the user will first select sun and mon .. then click on date button an so calendar view will be shown ..

I want the user just be able to select dates in days sun or mon .. i want to disable the other days and highlight them for example ..

what is the best way to do that?

i saw these two libraries:

https://cocoapods.org/pods/JTAppleCalendar

https://github.com/WenchaoD/FSCalendar

but didn't find anything that helps me do what i need using them..

what is the best way to do that?

3

There are 3 answers

13
Kuldeep On BEST ANSWER

You have to consider Sunday as 1, Monday as 2, Tuesday as 3 and so on Saturday 7.

Define below globally

fileprivate let gregorian: Calendar = Calendar(identifier: .gregorian)
    fileprivate lazy var dateFormatter2: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()

    var arrDates = NSMutableArray()

Write below line in viewDidLoad.

arrDates = self.getUserSelectedDates([1, 2], calender: self.calendarVW)

Here 1, 2 means user selected Monday and Tuesday (so This array contains only those dates which are Sunday and Monday)

Below is Function that returns Dates array Based on Day value like 1,2 and so on till 7.

func getUserSelectedDates(_ arrWeekDay: [Int], calender calenderVW: FSCalendar?) -> NSMutableArray {
        let arrUnAvailibilityDates = NSMutableArray()
        let currentDate: Date? = calenderVW?.currentPage
        //get calender
        let gregorianCalendar = Calendar.init(identifier: .gregorian)
        // Start out by getting just the year, month and day components of the current date.
        var components: DateComponents? = nil
        if let aDate = currentDate {
            components = gregorianCalendar.dateComponents([.year, .month, .day, .weekday], from: aDate)
        }
        // Change the Day component to 1 (for the first day of the month), and zero out the time components.
        components?.day = 1
        components?.hour = 0
        components?.minute = 0
        components?.second = 0
        //get first day of current month
        var firstDateOfCurMonth: Date? = nil
        if let aComponents = components {
            firstDateOfCurMonth = gregorianCalendar.date(from: aComponents)
        }
        //create new component to get weekday of first date
        var newcomponents: DateComponents? = nil
        if let aMonth = firstDateOfCurMonth {
            newcomponents = gregorianCalendar.dateComponents([.year, .month, .day, .weekday], from: aMonth)
        }
        let firstDateWeekDay: Int? = newcomponents?.weekday
        //get last month date
        let curMonth: Int? = newcomponents?.month
        newcomponents?.month = (curMonth ?? 0) + 1
        var templastDateOfCurMonth: Date? = nil
        if let aNewcomponents = newcomponents {
            templastDateOfCurMonth = gregorianCalendar.date(from: aNewcomponents)?.addingTimeInterval(-1)
        }
        // One second before the start of next month
        var lastcomponents: DateComponents? = nil
        if let aMonth = templastDateOfCurMonth {
            lastcomponents = gregorianCalendar.dateComponents([.year, .month, .day, .weekday], from: aMonth)
        }
        lastcomponents?.hour = 0
        lastcomponents?.minute = 0
        lastcomponents?.second = 0
        var lastDateOfCurMonth: Date? = nil
        if let aLastcomponents = lastcomponents {
            lastDateOfCurMonth = gregorianCalendar.date(from: aLastcomponents)
        }
        var dayDifference = DateComponents()
        dayDifference.calendar = gregorianCalendar

        if arrWeekDay.count == 0 {

        } else if arrWeekDay.count == 1 {
            let wantedWeekDay = Int(arrWeekDay[0])
            var firstWeekDateOfCurMonth: Date? = nil
            if wantedWeekDay == firstDateWeekDay {
                firstWeekDateOfCurMonth = firstDateOfCurMonth
            } else {
                var day: Int = wantedWeekDay - firstDateWeekDay!
                if day < 0 {
                    day += 7
                }
                day += 1
                components?.day = day
                firstWeekDateOfCurMonth = gregorianCalendar.date(from: components!)
            }
            var weekOffset: Int = 0
            var nextDate: Date? = firstWeekDateOfCurMonth
            repeat {
                let strDT: String = getSmallFormatedDate(convertCalendarDate(toNormalDate: nextDate))!
                arrUnAvailibilityDates.add(strDT)
                weekOffset += 1
                dayDifference.weekOfYear = weekOffset
                var date: Date? = nil
                if let aMonth = firstWeekDateOfCurMonth {
                    date = gregorianCalendar.date(byAdding: dayDifference, to: aMonth)
                }
                nextDate = date
            } while nextDate?.compare(lastDateOfCurMonth!) == .orderedAscending || nextDate?.compare(lastDateOfCurMonth!) == .orderedSame
        }
        else {
            for i in 0..<arrWeekDay.count {
                let wantedWeekDay = Int(arrWeekDay[i])
                var firstWeekDateOfCurMonth: Date? = nil
                if wantedWeekDay == firstDateWeekDay {
                    firstWeekDateOfCurMonth = firstDateOfCurMonth
                } else {
                    var day: Int = wantedWeekDay - firstDateWeekDay!
                    if day < 0 {
                        day += 7
                    }
                    day += 1
                    components?.day = day
                    firstWeekDateOfCurMonth = gregorianCalendar.date(from: components!)
                }


                var weekOffset: Int = 0
                var nextDate: Date? = firstWeekDateOfCurMonth
                repeat {
                    let strDT = getSmallFormatedDate(convertCalendarDate(toNormalDate: nextDate))
                    arrUnAvailibilityDates.add(strDT!)
                    weekOffset += 1
                    dayDifference.weekOfYear = weekOffset
                    var date: Date? = nil
                    if let aMonth = firstWeekDateOfCurMonth {
                        date = gregorianCalendar.date(byAdding: dayDifference, to: aMonth)
                    }
                    nextDate = date
                } while nextDate?.compare(lastDateOfCurMonth!) == .orderedAscending || nextDate?.compare(lastDateOfCurMonth!) == .orderedSame
            }
        }
        return arrUnAvailibilityDates
    }


func getSmallFormatedDate(_ localDate: Date?) -> String? {
        let dateFormatter = DateFormatter()
        let timeZone = NSTimeZone(name: "UTC")
        if let aZone = timeZone {
            dateFormatter.timeZone = aZone as TimeZone
        }
        dateFormatter.dateFormat = "yyyy-MM-dd"
        var dateString: String? = nil
        if let aDate = localDate {
            dateString = dateFormatter.string(from: aDate)
        }
        return dateString
    }

    func convertCalendarDate(toNormalDate selectedDate: Date?) -> Date? {
        let sourceTimeZone = NSTimeZone(abbreviation: "UTC")
        let destinationTimeZone = NSTimeZone.system as NSTimeZone
        var sourceGMTOffset: Int? = nil
        if let aDate = selectedDate {
            sourceGMTOffset = sourceTimeZone?.secondsFromGMT(for: aDate)
        }
        var destinationGMTOffset: Int? = nil
        if let aDate = selectedDate {
            destinationGMTOffset = destinationTimeZone.secondsFromGMT(for: aDate)
        }
        let interval1 = TimeInterval((destinationGMTOffset ?? 0) - (sourceGMTOffset ?? 0))
        var localDate: Date? = nil
        if let aDate = selectedDate {
            localDate = Date(timeInterval: interval1, since: aDate)
        }
        return localDate
    }

Below is FSCalendar delegates

extension ViewController: FSCalendarDelegate, FSCalendarDataSource, FSCalendarDelegateAppearance {
    func calendar(_ calendar: FSCalendar, boundingRectWillChange bounds: CGRect, animated: Bool) {
        self.view.layoutIfNeeded()
    }

    func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
    }

    func calendarCurrentPageDidChange(_ calendar: FSCalendar) {
        arrDates = self.getUserSelectedDates([3, 4], calender: self.calendarVW)
    }

    func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, titleDefaultColorFor date: Date) -> UIColor? {
        if arrDates.contains(dateFormatter2.string(from: date)) {
            return UIColor.green
        } else {
            return UIColor.red
        }
    }

    func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool {
        if arrDates.contains(dateFormatter2.string(from: date)) {
            return true
        }
        else {
            return false
        }
    }

}
3
Just a coder On

for JTApplecalendar this is easy

func calendar(_ calendar: JTAppleCalendarView, shouldSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) -> Bool {
    return cellState.day == .monday || cellState.day == .sunday
}

Done.

0
M Murteza On

For function calendar check Saturday or Sunday then it did not select. The solution for Swift 4.2:

 func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool {
   return CheckSatSunday(today: date)
}

// Check Today Is Saturday or Sunday

func CheckSatSunday(today:Date) ->Bool{

 var DayExist:Bool
   // let today = NSDate()

    let calendar = 
     NSCalendar(calendarIdentifier:NSCalendar.Identifier.gregorian)
    let components = calendar!.components([.weekday], from: today)

    if components.weekday == 1 {
        print("Hello Sunday")
        self.showToast(message: "Sunday is Off")
        DayExist = false
    } else if components.weekday == 7{
        print("Hello Saturday")
        self.showToast(message: "Saturday is Off")
         DayExist = false
    } else{
        print("It's not Saturday and  Sunday ")
        DayExist = true
    }
    print("weekday :\(String(describing: components.weekday)) ")
    return DayExist
}