I have 2 DatePickers where users can select hours and minutes.
Once a Picker is changed, the "calcDuration"-function is called that is supposed to calculate the difference in time and display it on a label in hours and minutes.
func calcDuration() {
let diffComponents = Calendar.current.dateComponents([.minute, .hour], from: datePicker1.date, to: datePicker2.date)
let hours = diffComponents.hour!
let minutes = diffComponents.minute!
durationLabel.text = "Δ \(hours)h : \(minutes)m"
}
If I run the app and increase the number of minutes in the lower datePicker (datePicker2) by one minute, the result of the "let minutes = diffComponents.minute!" is still zero.
Debugger-Result showing 0 minutes after DatePicker2 is changed by 1min
If I increase it further, it'll always show one minute less than the difference actually is.
Example:
Picker 1: 20:30 Picker 2: 20:31 -> calculated difference: 0 min
Picker 1: 20:30 Picker 2: 20:32 -> calculated difference: 1 min
Picker 1: 20:30 Picker 2: 20:41 -> calculated difference: 10 min
If I reduce the minute of the lower DatePicker (datePicker2), everything works fine and difference in minutes is shown correctly. Same effect when I increase the hours of datePicker2 by 1 -> result is 59min, if I reduce it by 1 hour its correct (-1h).
Example:
Picker 1: 20:30 Picker 2: 20:29 -> calculated difference: -1 min
Picker 1: 20:30 Picker 2: 20:20 -> calculated difference: -10 min
The only way to fix it is to move the upper DatePicker (datePicker1). No matter if I move the hours or the minutes of datePicker1, afterwards everything is working fine. So if I start the app, increase the hours of datePicker1 by 1h, then reduce it by 1h and finally change datePicker2 everything is working fine and calculated correctly.
Im working with iOS 14.5 / Xcode 12.5.
Thanks for your help!!
Edit:
The problem is that the internal initial picker dates are very slightly different from one another. This causes a "problem" which to you is expressed as a rounding error.
The solution is to set the picker dates to the very same date. Here's a way. In viewDidLoad
, say this:
let now = Date(timeIntervalSince1970: Double(Int(Date().timeIntervalSince1970)))
picker1.date = now
picker2.date = now
That gets rid of the rounding error and now the pickers behave as you expect.
Or, if you are setting the picker time yourself in code, do the same sort of thing. Eliminate the rounding error so that you are absolutely assigning the very same value to both pickers, initially.
The point is that, one way or another, the difference between the picker dates should be in integer values only.