Currently I have a UIDatePicker working like below:
But I'd like to make it work like below with start and end time?
Has anyone accomplished this customization on UIDatePicker?
The app that uses the UIDatePicker in this way is https://www.zeel.com/
Thanks!
While the answers of Rikn and Kayla point me in the right direction, they don't have the part of getting the dates as in the image I provided in the question so that's why I will put here the code how I did it.
class ViewController: UIViewController {
@IBOutlet weak var pickerView: UIPickerView!
var days = [Date]()
var startTimes = [Date]()
var endTimes = [Date]()
let dayFormatter = DateFormatter()
let timeFormatter = DateFormatter()
override func viewDidLoad() {
super.viewDidLoad()
dayFormatter.dateFormat = "EE d MMM"
timeFormatter.timeStyle = .short
days = setDays()
startTimes = setStartTimes()
endTimes = setEndTimes()
}
}
extension ViewController {
func getDays(of date: Date) -> [Date] {
var dates = [Date]()
let calendar = Calendar.current
// first date
var currentDate = date
// adding 30 days to current date
let oneMonthFromNow = calendar.date(byAdding: .day, value: 30, to: currentDate)
// last date
let endDate = oneMonthFromNow
while currentDate <= endDate! {
dates.append(currentDate)
currentDate = calendar.date(byAdding: .day, value: 1, to: currentDate)!
}
return dates
}
func getTimes(of date: Date) -> [Date] {
var times = [Date]()
var currentDate = date
currentDate = Calendar.current.date(bySetting: .hour, value: 7, of: currentDate)!
currentDate = Calendar.current.date(bySetting: .minute, value: 00, of: currentDate)!
let calendar = Calendar.current
let interval = 60
var nextDiff = interval - calendar.component(.minute, from: currentDate) % interval
var nextDate = calendar.date(byAdding: .minute, value: nextDiff, to: currentDate) ?? Date()
var hour = Calendar.current.component(.hour, from: nextDate)
while(hour < 23) {
times.append(nextDate)
nextDiff = interval - calendar.component(.minute, from: nextDate) % interval
nextDate = calendar.date(byAdding: .minute, value: nextDiff, to: nextDate) ?? Date()
hour = Calendar.current.component(.hour, from: nextDate)
}
return times
}
func setDays() -> [Date] {
let today = Date()
return getDays(of: today)
}
func setStartTimes() -> [Date] {
let today = Date()
return getTimes(of: today)
}
func setEndTimes() -> [Date] {
let today = Date()
return getTimes(of: today)
}
func getDayString(from: Date) -> String {
return dayFormatter.string(from: from)
}
func getTimeString(from: Date) -> String {
return timeFormatter.string(from: from)
}
}
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
switch component {
case 0:
return days.count
case 1:
return startTimes.count
case 2:
return endTimes.count
default:
return 0
}
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
var label: UILabel
if let view = view as? UILabel {
label = view
} else {
label = UILabel()
}
label.textColor = .black
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 15)
var text = ""
switch component {
case 0:
text = getDayString(from: days[row])
case 1:
text = getTimeString(from: startTimes[row])
case 2:
text = getTimeString(from: endTimes[row])
default:
break
}
label.text = text
return label
}
}