问题
I'm using fscalender and am disabling user's selected days like this:
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
}
}
}
which is working perfectly .. now am trying to disable past days in fscalender .. i have tried this:
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
}
}
but it didn't work for me...
also i noticed that the current date is wrong! i keep getting
2018-04-30 21:00:00 +0000
while today's date is 2018-05-12
how to solve this and disable past days?
回答1:
You just need to compare selected date with current date. If it's Ascending than return false
otherwise return true
in shouldSelect
method like below.
Try only 1 solution.
1. SOLUTION (It display previous month while you swipe to see previous month, This solution consider current date as past date because there's time difference)
func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool {
if date .compare(Date()) == .orderedAscending {
return false
}
else {
return true
}
}
2. SOLUTION (This will not display Past Months, In This solution you can also select current date)
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)!
}
来源:https://stackoverflow.com/questions/50307950/disabling-past-days-in-fscalendar