Reputation: 13803
I have a pop up view controller like the picture above. In viewDidLoad
, I set the minimum date for picker view is now ( Date() ), and in storyboard, I set the interval time in 15 minutes. here is the code I use
class DateTimePickerVC: UIViewController {
@IBOutlet var dateTimePickerView: UIDatePicker!
var selectedDateAndTime : Date?
override func viewDidLoad() {
super.viewDidLoad()
// to make live update of selected date
dateTimePickerView.addTarget(self, action: #selector(DateTimePickerVC.datePickerValueChanged), for: UIControl.Event.valueChanged)
// minimum date is now
dateTimePickerView.minimumDate = Date()
// set initial value, to avoid nil value
selectedDateAndTime = dateTimePickerView.date
}
@objc func datePickerValueChanged (datePicker: UIDatePicker) {
selectedDateAndTime = datePicker.date
}
@IBAction func pickedButtonDidPressed(_ sender: Any) {
// send date 'selectedDateAndTime' to other VC
}
}
I have 2 problems in here:
let say the user open that pop up datePickerVC at 16:28. I expect the minimum date and time that will be displayed at that pop up will be "Today 16:30", but at my case is "Today 16:15". how to solve this issue?
to avoid nil value of selectedDateAndTime
, in viewDidLoad
I set selectedDateAndTime = dateTimePickerView.date
, so I hope that when the user immediately tap the save button and send the date
to other VC without scrolling the date picker, it will get the minimum date that displayed in datePicker. let say the user open that pop up at 16:08, I expect the selected date to be the minimum date and time displayed at datePickerView (today 16:15), but the actual date value I get is (Today 16:08), because I set the datePicker.minimumDate = Date()
(now). how to get the minimum date that displayed on datePicker view ?
Upvotes: 1
Views: 745
Reputation: 204
enum DateRoundingType {
case round
case ceil
case floor
}
extension Date {
func rounded(minutes: TimeInterval, rounding: DateRoundingType = .round) -> Date {
return rounded(seconds: minutes * 60, rounding: rounding)
}
func rounded(seconds: TimeInterval, rounding: DateRoundingType = .round) -> Date {
var roundedInterval: TimeInterval = 0
switch rounding {
case .round:
roundedInterval = (timeIntervalSinceReferenceDate / seconds).rounded() * seconds
case .ceil:
roundedInterval = ceil(timeIntervalSinceReferenceDate / seconds) * seconds
case .floor:
roundedInterval = floor(timeIntervalSinceReferenceDate / seconds) * seconds
}
return Date(timeIntervalSinceReferenceDate: roundedInterval)
}
}
Usage:
//add below code in viewDidLoad()
let nextMinuteIntervalDate = Date().rounded(
minutes: 15,
rounding: .ceil
)
dateTimePickerView.minimumDate = nextMinuteIntervalDate
dateTimePickerView.setDate(nextMinuteIntervalDate, animated: true)
Upvotes: 2
Reputation: 572
I think you must be aware of the fact that why it is showing 16:15 as the time (16:28) is still logically less than 16:30 and I don't think you can do that as it doesn't make any logical sense
By the declaration of minimumDate
:
var minimumDate: Date? { get set }
As minimumDate
has a get property, you can just fetch the minimum date using :
// Since it is an optional , we have to safe unwrap it
if let minimumDate = datePicker.minimumDate {
// Use your minimumDate variable here
}
Upvotes: 1