Restricting hours and minutes in DatePicker- swift?

Viewed 1423

hi guys im trying to create a time picker which hours are only from (2pm - 9pm) and minutes are incremented by 30 this is the picture of timePicker that i want to create here is my code

func creatTimePicker() {
        timePicker.datePickerMode = .time
        timePicker.minuteInterval = 30
        let timeformatter = DateFormatter()
        timeformatter.dateFormat = "HH:mm"

        let min = timeformatter.date(from: "5:00")
        let max = timeformatter.date(from: "9:00")
        timePicker.minimumDate = min
        timePicker.maximumDate = max
        self.contentView.addSubview(timePicker)
    } 

the problem is hour starts 1-12 and minute starts 00-59 what is the problem? thank you

2 Answers

You can use Calendar to constraint the time range for UIDatePicker()

        let picker = UIDatePicker()
        picker.datePickerMode = .time
        
        let minDate = Calendar.current.date(bySettingHour: 14, minute: 0, second: 0, of: Date()) // 2PM
        
        let maxDate = Calendar.current.date(bySettingHour: 21, minute: 0, second: 0, of: Date()) // 9PM
    
        picker.minimumDate = minDate
        picker.maximumDate = maxDate

This won't let user select time outside the specified time range.

In case you want to show only these hours

You can use UIPickerView

Example:

let picker = UIPickerView()
picker.dataSource = self
picker.delegate = self

let hoursRange = Array(5...9)

// Data source

func numberOfComponents(in: UIPickerView) -> Int {
        return 2
    }
    
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        print("Com :\(component)")
        if component == 0 {
            return hoursRange.count
        }
        
        return 1 // For the PM indicator
    }

// Delegate
    
func pickerView(_ pickerView: UIPickerView,
     titleForRow row: Int,
     forComponent component: Int) -> String? {
        switch component {
        case 0:
            return "\(hoursRange[row])"
        case 1:
            return "AM"
        default:
            return nil
        }
    }

The problem is that you need to set the date picker date property to match the minimum date as well. You need also to set the date formatter default date to today and don't forget to set the locale to "en_US_POSIX" when parsing your date string time:

extension Formatter {
    static let time: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = .init(identifier: "em_US_POSIX")
        formatter.dateFormat = "HH:mm"
        return formatter
    }()
}

let timePicker = UIDatePicker()
func creatTimePicker() {
    Formatter.time.defaultDate = Calendar.current.startOfDay(for: Date())
    let minimumDate = Formatter.time.date(from: "14:00")!
    let maximumDate = Formatter.time.date(from: "21:00")!
    timePicker.date = minimumDate 
    timePicker.datePickerMode = .time
    timePicker.minuteInterval = 30
    timePicker.minimumDate = minimumDate
    timePicker.maximumDate = maximumDate
    self.contentView.addSubview(timePicker)
}
Related