Skip to content

Commit 1abd832

Browse files
committed
Fix layout for calendars where first week day is different from Monday. Related issue #18
1 parent a50ebea commit 1abd832

File tree

5 files changed

+68
-34
lines changed

5 files changed

+68
-34
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Ilya Kharlamov on 9/12/22.
6+
//
7+
8+
import Foundation
9+
10+
internal extension Calendar {
11+
var lastWeekday: Int {
12+
let numDays = self.weekdaySymbols.count
13+
let res = (self.firstWeekday + numDays - 1) % numDays
14+
return res != 0 ? res : self.weekdaySymbols.count
15+
}
16+
}

Sources/Models/Config.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ public struct FastisConfig {
3232

3333
private init() {}
3434

35+
/**
36+
Base calendar used to build a view
37+
38+
Default value — `.current`
39+
*/
40+
public var calendar: Calendar = .current
41+
3542
/// Base view controller (`cancelButtonTitle`, `doneButtonTitle`, etc.)
3643
public var controller = FastisConfig.Controller()
3744

Sources/Views/Controller.swift

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ open class FastisController<Value: FastisValue>: UIViewController, JTACMonthView
9494
}()
9595

9696
private lazy var weekView: WeekView = {
97-
let view = WeekView(config: self.config.weekView)
97+
let view = WeekView(calendar: self.config.calendar, config: self.config.weekView)
9898
view.translatesAutoresizingMaskIntoConstraints = false
9999
return view
100100
}()
@@ -139,7 +139,6 @@ open class FastisController<Value: FastisValue>: UIViewController, JTACMonthView
139139
private let dayCellReuseIdentifier = "DayCellReuseIdentifier"
140140
private let monthHeaderReuseIdentifier = "MonthHeaderReuseIdentifier"
141141
private var viewConfigs: [IndexPath: DayCell.ViewConfig] = [:]
142-
private var currentCalendar: Calendar = .autoupdatingCurrent
143142
private var privateMinimumDate: Date?
144143
private var privateMaximumDate: Date?
145144
private var privateSelectMonthOnHeaderTap: Bool = false
@@ -347,7 +346,8 @@ open class FastisController<Value: FastisValue>: UIViewController, JTACMonthView
347346
let newConfig = DayCell.makeViewConfig(for: cellState,
348347
minimumDate: self.privateMinimumDate,
349348
maximumDate: self.privateMaximumDate,
350-
rangeValue: self.value as? FastisRange)
349+
rangeValue: self.value as? FastisRange,
350+
calendar: self.config.calendar)
351351
self.viewConfigs[indexPath] = newConfig
352352
cell.applyConfig(self.config)
353353
cell.configure(for: newConfig)
@@ -399,23 +399,23 @@ open class FastisController<Value: FastisValue>: UIViewController, JTACMonthView
399399
let dateRangeChangesDisabled = !allowDateRangeChanges
400400
let rangeSelected = !currentValue.fromDate.isInSameDay(date: currentValue.toDate)
401401
if dateRangeChangesDisabled && rangeSelected {
402-
newValue = .from(date.startOfDay(in: self.currentCalendar), to: date.endOfDay(in: self.currentCalendar))
403-
} else if date.isInSameDay(in: self.currentCalendar, date: currentValue.fromDate) {
404-
let newToDate = date.endOfDay(in: self.currentCalendar)
402+
newValue = .from(date.startOfDay(in: self.config.calendar), to: date.endOfDay(in: self.config.calendar))
403+
} else if date.isInSameDay(in: self.config.calendar, date: currentValue.fromDate) {
404+
let newToDate = date.endOfDay(in: self.config.calendar)
405405
newValue = .from(currentValue.fromDate, to: newToDate)
406-
} else if date.isInSameDay(in: self.currentCalendar, date: currentValue.toDate) {
407-
let newFromDate = date.startOfDay(in: self.currentCalendar)
406+
} else if date.isInSameDay(in: self.config.calendar, date: currentValue.toDate) {
407+
let newFromDate = date.startOfDay(in: self.config.calendar)
408408
newValue = .from(newFromDate, to: currentValue.toDate)
409409
} else if date < currentValue.fromDate {
410-
let newFromDate = date.startOfDay(in: self.currentCalendar)
410+
let newFromDate = date.startOfDay(in: self.config.calendar)
411411
newValue = .from(newFromDate, to: currentValue.toDate)
412412
} else {
413-
let newToDate = date.endOfDay(in: self.currentCalendar)
413+
let newToDate = date.endOfDay(in: self.config.calendar)
414414
newValue = .from(currentValue.fromDate, to: newToDate)
415415
}
416416

417417
} else {
418-
newValue = .from(date.startOfDay(in: self.currentCalendar), to: date.endOfDay(in: self.currentCalendar))
418+
newValue = .from(date.startOfDay(in: self.config.calendar), to: date.endOfDay(in: self.config.calendar))
419419
}
420420

421421
self.value = newValue as? Value
@@ -441,30 +441,30 @@ open class FastisController<Value: FastisValue>: UIViewController, JTACMonthView
441441

442442
let dateFormatter = DateFormatter()
443443
dateFormatter.dateFormat = "yyyy MM dd"
444-
dateFormatter.timeZone = self.currentCalendar.timeZone
445-
dateFormatter.locale = self.currentCalendar.locale
444+
dateFormatter.timeZone = self.config.calendar.timeZone
445+
dateFormatter.locale = self.config.calendar.locale
446446
var startDate = dateFormatter.date(from: "2000 01 01")!
447447
var endDate = dateFormatter.date(from: "2030 12 01")!
448448

449449
if let maximumDate = self.privateMaximumDate,
450-
let endOfNextMonth = self.currentCalendar.date(byAdding: .month, value: 2, to: maximumDate)?
451-
.endOfMonth(in: self.currentCalendar) {
450+
let endOfNextMonth = self.config.calendar.date(byAdding: .month, value: 2, to: maximumDate)?
451+
.endOfMonth(in: self.config.calendar) {
452452
endDate = endOfNextMonth
453453
}
454454

455455
if let minimumDate = self.privateMinimumDate,
456-
let startOfPreviousMonth = self.currentCalendar.date(byAdding: .month, value: -2, to: minimumDate)?
457-
.startOfMonth(in: self.currentCalendar) {
456+
let startOfPreviousMonth = self.config.calendar.date(byAdding: .month, value: -2, to: minimumDate)?
457+
.startOfMonth(in: self.config.calendar) {
458458
startDate = startOfPreviousMonth
459459
}
460460

461461
let parameters = ConfigurationParameters(startDate: startDate,
462462
endDate: endDate,
463463
numberOfRows: 6,
464-
calendar: self.currentCalendar,
464+
calendar: self.config.calendar,
465465
generateInDates: .forAllMonths,
466466
generateOutDates: .tillEndOfRow,
467-
firstDayOfWeek: .monday,
467+
firstDayOfWeek: nil,
468468
hasStrictBoundaries: true)
469469
return parameters
470470
}
@@ -475,16 +475,16 @@ open class FastisController<Value: FastisValue>: UIViewController, JTACMonthView
475475
header.configure(for: range.start)
476476
if self.privateSelectMonthOnHeaderTap, Value.mode == .range {
477477
header.tapHandler = {
478-
var fromDate = range.start.startOfMonth(in: self.currentCalendar)
479-
var toDate = range.start.endOfMonth(in: self.currentCalendar)
478+
var fromDate = range.start.startOfMonth(in: self.config.calendar)
479+
var toDate = range.start.endOfMonth(in: self.config.calendar)
480480
if let minDate = self.minimumDate {
481481
if toDate < minDate { return } else if fromDate < minDate {
482-
fromDate = minDate.startOfDay(in: self.currentCalendar)
482+
fromDate = minDate.startOfDay(in: self.config.calendar)
483483
}
484484
}
485485
if let maxDate = self.maximumDate {
486486
if fromDate > maxDate { return } else if toDate > maxDate {
487-
toDate = maxDate.endOfDay(in: self.currentCalendar)
487+
toDate = maxDate.endOfDay(in: self.config.calendar)
488488
}
489489
}
490490
let newValue: FastisRange = .from(fromDate, to: toDate)

Sources/Views/DayCell.swift

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,13 @@ class DayCell: JTACDayCell {
133133
NSLayoutConstraint.activate(self.rangeViewBottomAnchorConstraints)
134134
}
135135

136-
public static func makeViewConfig(for state: CellState, minimumDate: Date?, maximumDate: Date?, rangeValue: FastisRange?) -> ViewConfig {
136+
public static func makeViewConfig(
137+
for state: CellState,
138+
minimumDate: Date?,
139+
maximumDate: Date?,
140+
rangeValue: FastisRange?,
141+
calendar: Calendar
142+
) -> ViewConfig {
137143

138144
var config = ViewConfig()
139145

@@ -162,10 +168,10 @@ class DayCell: JTACDayCell {
162168

163169
if showRangeView {
164170

165-
if state.day == .monday {
171+
if state.day.rawValue == calendar.firstWeekday {
166172
config.rangeView.leftSideState = .rounded
167173
config.rangeView.rightSideState = .squared
168-
} else if state.day == .sunday {
174+
} else if state.day.rawValue == calendar.lastWeekday {
169175
config.rangeView.leftSideState = .squared
170176
config.rangeView.rightSideState = .rounded
171177
} else {
@@ -201,10 +207,10 @@ class DayCell: JTACDayCell {
201207
case .left, .right, .middle:
202208
config.isSelectedViewHidden = position == .middle
203209

204-
if position == .right && state.day == .monday {
210+
if position == .right && state.day.rawValue == calendar.firstWeekday {
205211
config.rangeView.leftSideState = .rounded
206212

207-
} else if position == .left && state.day == .sunday {
213+
} else if position == .left && state.day.rawValue == calendar.lastWeekday {
208214
config.rangeView.rightSideState = .rounded
209215

210216
} else if position == .left {
@@ -213,11 +219,11 @@ class DayCell: JTACDayCell {
213219
} else if position == .right {
214220
config.rangeView.leftSideState = .squared
215221

216-
} else if state.day == .monday {
222+
} else if state.day.rawValue == calendar.firstWeekday {
217223
config.rangeView.leftSideState = .rounded
218224
config.rangeView.rightSideState = .squared
219225

220-
} else if state.day == .sunday {
226+
} else if state.day.rawValue == calendar.lastWeekday {
221227
config.rangeView.leftSideState = .squared
222228
config.rangeView.rightSideState = .rounded
223229

Sources/Views/WeekView.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ class WeekView: UIView {
2626
// MARK: - Variables
2727

2828
private let config: FastisConfig.WeekView
29+
private let calendar: Calendar
2930

3031
// MARK: - Lifecycle
3132

32-
init(config: FastisConfig.WeekView) {
33+
init(calendar: Calendar, config: FastisConfig.WeekView) {
3334
self.config = config
35+
self.calendar = calendar
3436
super.init(frame: .zero)
3537
self.configureUI()
3638
self.configureSubviews()
@@ -50,9 +52,11 @@ class WeekView: UIView {
5052
}
5153

5254
private func configureSubviews() {
53-
var weekDays = self.config.calendar.shortWeekdaySymbols
54-
weekDays.append(weekDays.remove(at: 0))
55-
for weekdaySymbol in weekDays {
55+
let numDays = self.calendar.shortStandaloneWeekdaySymbols.count
56+
let first = self.calendar.firstWeekday - 1
57+
let end = first + numDays - 1
58+
let days = (first...end).map({ self.calendar.shortStandaloneWeekdaySymbols[$0 % numDays] })
59+
for weekdaySymbol in days {
5660
self.stackView.addArrangedSubview(self.makeWeekLabel(for: weekdaySymbol))
5761
}
5862
self.addSubview(self.stackView)
@@ -95,6 +99,7 @@ extension FastisConfig {
9599

96100
Default value — `.current`
97101
*/
102+
@available(*, unavailable, message: "Use FastisConfig.calendar propery instead")
98103
public var calendar: Calendar = .current
99104

100105
/**

0 commit comments

Comments
 (0)