在 fscalendar 中禁用过去的日子

Posted

技术标签:

【中文标题】在 fscalendar 中禁用过去的日子【英文标题】:disabling past days in fscalendar 【发布时间】:2018-05-12 15:38:46 【问题描述】:

我正在使用 fscalender 并且正在禁用用户选择的日期,如下所示:

        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)
        print(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

   extension CalenderViewController: 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) 
    self.date = dateFormatter2.string(from: date)


func calendarCurrentPageDidChange(_ calendar: FSCalendar) 
    arrDates = self.getUserSelectedDates(days, calender: self.calendar)
    calendar.reloadData()


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


func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool 

    if arrDates.contains(dateFormatter2.string(from: date))) 
        return true
    
    else 
        return false
    



这是完美的工作..现在我试图在 fscalender 中禁用过去的日子..我试过这个:

 func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool 

    if arrDates.contains(dateFormatter2.string(from: date)) && (date > calendar.currentPage) 
        return true
    
    else 
        return false
    

但它对我不起作用......

我还注意到当前日期是错误的!我不断得到

2018-04-30 21:00:00 +0000

而今天的日期是 2018-05-12

如何解决这个问题并禁用过去的日子?

【问题讨论】:

【参考方案1】:

您只需将所选日期与当前日期进行比较。如果它比return false 升序,否则return trueshouldSelect 方法中,如下所示。

只尝试一种解决方案。

1.解决方案(当您滑动查看上个月时,它会显示上个月,此解决方案将当前日期视为过去日期,因为存在时差)

func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool 
    if date .compare(Date()) == .orderedAscending 
        return false
    
    else 
        return true
    

2。解决方案(这不会显示过去的月份,在此解决方案中您还可以选择当前日期)

func minimumDate(for calendar: FSCalendar) -> Date 
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    let myString = formatter.string(from: Date())
    let yourDate = formatter.date(from: myString)
    formatter.dateFormat = "yyyy-MM-dd"
    let strCurrentDate = formatter.string(from: yourDate!)
    return self.dateFormatter2.date(from: strCurrentDate)!

【讨论】:

【参考方案2】:

您可以使用此委托方法禁用过去的日期

 func minimumDate(for calendar: FSCalendar) -> Date 
    return Date()
 

【讨论】:

以上是关于在 fscalendar 中禁用过去的日子的主要内容,如果未能解决你的问题,请参考以下文章

如何在 FSCalendar swift 中禁用用户交互?

在 FSCalendar 中显示来自 API 的事件

在 FSCalendar UIView 上放置按钮

FSCalendar:从头开始查看标题?

如何在 Xamarin.iOS 的 FSCalendar 中添加事件

如何在 FSCalendar 中删除所有周末