diff --git a/Sources/Extensions/Calendar+LastWeekday.swift b/Sources/Extensions/Calendar+LastWeekday.swift new file mode 100644 index 0000000..3e16dde --- /dev/null +++ b/Sources/Extensions/Calendar+LastWeekday.swift @@ -0,0 +1,16 @@ +// +// File.swift +// +// +// Created by Ilya Kharlamov on 9/12/22. +// + +import Foundation + +internal extension Calendar { + var lastWeekday: Int { + let numDays = self.weekdaySymbols.count + let res = (self.firstWeekday + numDays - 1) % numDays + return res != 0 ? res : self.weekdaySymbols.count + } +} diff --git a/Sources/Models/Config.swift b/Sources/Models/Config.swift index e49eb58..03fcde0 100644 --- a/Sources/Models/Config.swift +++ b/Sources/Models/Config.swift @@ -32,6 +32,13 @@ public struct FastisConfig { private init() {} + /** + Base calendar used to build a view + + Default value — `.current` + */ + public var calendar: Calendar = .current + /// Base view controller (`cancelButtonTitle`, `doneButtonTitle`, etc.) public var controller = FastisConfig.Controller() diff --git a/Sources/Views/Controller.swift b/Sources/Views/Controller.swift index 7bf3d48..8ee3731 100644 --- a/Sources/Views/Controller.swift +++ b/Sources/Views/Controller.swift @@ -94,7 +94,7 @@ open class FastisController: UIViewController, JTACMonthView }() private lazy var weekView: WeekView = { - let view = WeekView(config: self.config.weekView) + let view = WeekView(calendar: self.config.calendar, config: self.config.weekView) view.translatesAutoresizingMaskIntoConstraints = false return view }() @@ -139,7 +139,6 @@ open class FastisController: UIViewController, JTACMonthView private let dayCellReuseIdentifier = "DayCellReuseIdentifier" private let monthHeaderReuseIdentifier = "MonthHeaderReuseIdentifier" private var viewConfigs: [IndexPath: DayCell.ViewConfig] = [:] - private var currentCalendar: Calendar = .autoupdatingCurrent private var privateMinimumDate: Date? private var privateMaximumDate: Date? private var privateSelectMonthOnHeaderTap: Bool = false @@ -347,7 +346,8 @@ open class FastisController: UIViewController, JTACMonthView let newConfig = DayCell.makeViewConfig(for: cellState, minimumDate: self.privateMinimumDate, maximumDate: self.privateMaximumDate, - rangeValue: self.value as? FastisRange) + rangeValue: self.value as? FastisRange, + calendar: self.config.calendar) self.viewConfigs[indexPath] = newConfig cell.applyConfig(self.config) cell.configure(for: newConfig) @@ -399,23 +399,23 @@ open class FastisController: UIViewController, JTACMonthView let dateRangeChangesDisabled = !allowDateRangeChanges let rangeSelected = !currentValue.fromDate.isInSameDay(date: currentValue.toDate) if dateRangeChangesDisabled && rangeSelected { - newValue = .from(date.startOfDay(in: self.currentCalendar), to: date.endOfDay(in: self.currentCalendar)) - } else if date.isInSameDay(in: self.currentCalendar, date: currentValue.fromDate) { - let newToDate = date.endOfDay(in: self.currentCalendar) + newValue = .from(date.startOfDay(in: self.config.calendar), to: date.endOfDay(in: self.config.calendar)) + } else if date.isInSameDay(in: self.config.calendar, date: currentValue.fromDate) { + let newToDate = date.endOfDay(in: self.config.calendar) newValue = .from(currentValue.fromDate, to: newToDate) - } else if date.isInSameDay(in: self.currentCalendar, date: currentValue.toDate) { - let newFromDate = date.startOfDay(in: self.currentCalendar) + } else if date.isInSameDay(in: self.config.calendar, date: currentValue.toDate) { + let newFromDate = date.startOfDay(in: self.config.calendar) newValue = .from(newFromDate, to: currentValue.toDate) } else if date < currentValue.fromDate { - let newFromDate = date.startOfDay(in: self.currentCalendar) + let newFromDate = date.startOfDay(in: self.config.calendar) newValue = .from(newFromDate, to: currentValue.toDate) } else { - let newToDate = date.endOfDay(in: self.currentCalendar) + let newToDate = date.endOfDay(in: self.config.calendar) newValue = .from(currentValue.fromDate, to: newToDate) } } else { - newValue = .from(date.startOfDay(in: self.currentCalendar), to: date.endOfDay(in: self.currentCalendar)) + newValue = .from(date.startOfDay(in: self.config.calendar), to: date.endOfDay(in: self.config.calendar)) } self.value = newValue as? Value @@ -441,30 +441,30 @@ open class FastisController: UIViewController, JTACMonthView let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy MM dd" - dateFormatter.timeZone = self.currentCalendar.timeZone - dateFormatter.locale = self.currentCalendar.locale + dateFormatter.timeZone = self.config.calendar.timeZone + dateFormatter.locale = self.config.calendar.locale var startDate = dateFormatter.date(from: "2000 01 01")! var endDate = dateFormatter.date(from: "2030 12 01")! if let maximumDate = self.privateMaximumDate, - let endOfNextMonth = self.currentCalendar.date(byAdding: .month, value: 2, to: maximumDate)? - .endOfMonth(in: self.currentCalendar) { + let endOfNextMonth = self.config.calendar.date(byAdding: .month, value: 2, to: maximumDate)? + .endOfMonth(in: self.config.calendar) { endDate = endOfNextMonth } if let minimumDate = self.privateMinimumDate, - let startOfPreviousMonth = self.currentCalendar.date(byAdding: .month, value: -2, to: minimumDate)? - .startOfMonth(in: self.currentCalendar) { + let startOfPreviousMonth = self.config.calendar.date(byAdding: .month, value: -2, to: minimumDate)? + .startOfMonth(in: self.config.calendar) { startDate = startOfPreviousMonth } let parameters = ConfigurationParameters(startDate: startDate, endDate: endDate, numberOfRows: 6, - calendar: self.currentCalendar, + calendar: self.config.calendar, generateInDates: .forAllMonths, generateOutDates: .tillEndOfRow, - firstDayOfWeek: .monday, + firstDayOfWeek: nil, hasStrictBoundaries: true) return parameters } @@ -475,16 +475,16 @@ open class FastisController: UIViewController, JTACMonthView header.configure(for: range.start) if self.privateSelectMonthOnHeaderTap, Value.mode == .range { header.tapHandler = { - var fromDate = range.start.startOfMonth(in: self.currentCalendar) - var toDate = range.start.endOfMonth(in: self.currentCalendar) + var fromDate = range.start.startOfMonth(in: self.config.calendar) + var toDate = range.start.endOfMonth(in: self.config.calendar) if let minDate = self.minimumDate { if toDate < minDate { return } else if fromDate < minDate { - fromDate = minDate.startOfDay(in: self.currentCalendar) + fromDate = minDate.startOfDay(in: self.config.calendar) } } if let maxDate = self.maximumDate { if fromDate > maxDate { return } else if toDate > maxDate { - toDate = maxDate.endOfDay(in: self.currentCalendar) + toDate = maxDate.endOfDay(in: self.config.calendar) } } let newValue: FastisRange = .from(fromDate, to: toDate) diff --git a/Sources/Views/DayCell.swift b/Sources/Views/DayCell.swift index 55489c0..8801e99 100644 --- a/Sources/Views/DayCell.swift +++ b/Sources/Views/DayCell.swift @@ -133,7 +133,13 @@ class DayCell: JTACDayCell { NSLayoutConstraint.activate(self.rangeViewBottomAnchorConstraints) } - public static func makeViewConfig(for state: CellState, minimumDate: Date?, maximumDate: Date?, rangeValue: FastisRange?) -> ViewConfig { + public static func makeViewConfig( + for state: CellState, + minimumDate: Date?, + maximumDate: Date?, + rangeValue: FastisRange?, + calendar: Calendar + ) -> ViewConfig { var config = ViewConfig() @@ -162,10 +168,10 @@ class DayCell: JTACDayCell { if showRangeView { - if state.day == .monday { + if state.day.rawValue == calendar.firstWeekday { config.rangeView.leftSideState = .rounded config.rangeView.rightSideState = .squared - } else if state.day == .sunday { + } else if state.day.rawValue == calendar.lastWeekday { config.rangeView.leftSideState = .squared config.rangeView.rightSideState = .rounded } else { @@ -201,10 +207,10 @@ class DayCell: JTACDayCell { case .left, .right, .middle: config.isSelectedViewHidden = position == .middle - if position == .right && state.day == .monday { + if position == .right && state.day.rawValue == calendar.firstWeekday { config.rangeView.leftSideState = .rounded - } else if position == .left && state.day == .sunday { + } else if position == .left && state.day.rawValue == calendar.lastWeekday { config.rangeView.rightSideState = .rounded } else if position == .left { @@ -213,11 +219,11 @@ class DayCell: JTACDayCell { } else if position == .right { config.rangeView.leftSideState = .squared - } else if state.day == .monday { + } else if state.day.rawValue == calendar.firstWeekday { config.rangeView.leftSideState = .rounded config.rangeView.rightSideState = .squared - } else if state.day == .sunday { + } else if state.day.rawValue == calendar.lastWeekday { config.rangeView.leftSideState = .squared config.rangeView.rightSideState = .rounded diff --git a/Sources/Views/WeekView.swift b/Sources/Views/WeekView.swift index 0271520..2d1301c 100644 --- a/Sources/Views/WeekView.swift +++ b/Sources/Views/WeekView.swift @@ -26,11 +26,13 @@ class WeekView: UIView { // MARK: - Variables private let config: FastisConfig.WeekView + private let calendar: Calendar // MARK: - Lifecycle - init(config: FastisConfig.WeekView) { + init(calendar: Calendar, config: FastisConfig.WeekView) { self.config = config + self.calendar = calendar super.init(frame: .zero) self.configureUI() self.configureSubviews() @@ -50,9 +52,11 @@ class WeekView: UIView { } private func configureSubviews() { - var weekDays = self.config.calendar.shortWeekdaySymbols - weekDays.append(weekDays.remove(at: 0)) - for weekdaySymbol in weekDays { + let numDays = self.calendar.shortStandaloneWeekdaySymbols.count + let first = self.calendar.firstWeekday - 1 + let end = first + numDays - 1 + let days = (first...end).map({ self.calendar.shortStandaloneWeekdaySymbols[$0 % numDays] }) + for weekdaySymbol in days { self.stackView.addArrangedSubview(self.makeWeekLabel(for: weekdaySymbol)) } self.addSubview(self.stackView) @@ -95,6 +99,7 @@ extension FastisConfig { Default value — `.current` */ + @available(*, unavailable, message: "Use FastisConfig.calendar propery instead") public var calendar: Calendar = .current /**