In my application, I need to get the previous 4 hours, not 4 hours of the current date.
For example:
- if he is
March 05, 10:00 am , then I should expect to return: March 05, 4:00 am - if he is
March 05, 02:00 am , then I should expect to return: March 04, 4:00 am
To achieve this, I use Calendar.nextDate . It works well for the everyday month, except for the last day of each month.
This is an example of a happy journey where it works as expected:
let components = DateComponents(hour: 4, minute: 0, second: 0) let date = Calendar.current.date(from: DateComponents(year: 2018, month: 03, day: 05, hour: 13, minute: 25, second: 0))! let result = Calendar.current.nextDate(after: date, matching: components, matchingPolicy: .nextTime, direction: .backward)
Output:
date = "Mar 5, 2018 at 1:25 PM" result = "Mar 5, 2018 at 4:00 AM"
This is an example of a dark sad path where it does NOT act as expected:
let components = DateComponents(hour: 4, minute: 0, second: 0) let date = Calendar.current.date(from: DateComponents(year: 2018, month: 03, day: 31, hour: 13, minute: 25, second: 0))! let result = Calendar.current.nextDate(after: date, matching: components, matchingPolicy: .nextTime, direction: .backward)
Output:
date = "Mar 31, 2018 at 1:25 PM" result = "Mar 30, 2018 at 4:00 AM" // it should give me this instead: "Mar 31, 2018 at 4:00 AM"
Any idea why this is happening? is this a bug in Apple code, should I report it? or am i using it wrong?
If this is Apple's error, is there another way to achieve what I need at the same time?
Update:
Looking at some Swift source code, I noticed that the problem was not with the Calendar.nextDate() function. nextDate() uses Calendar.enumerateDates() and one where the real problem exists. However, I could not find the source code for this function. This is a bug using Calendar.enumerateDates() :
let components = DateComponents(hour: 4, minute: 0, second: 0) let date = Calendar.current.date(from: DateComponents(year: 2018, month: 03, day: 31, hour: 13, minute: 25, second: 0))! Calendar.current.enumerateDates(startingAfter: inputDate, matching: components, matchingPolicy: .nextTime, direction: .backward) { (date, exactMatch, stop) in let result = date // result = "Mar 30, 2018 at 4:00 AM" stop = true }
Also, this is a similar issue: Swift Calendar.enumerateDates gives an incorrect result when launched in February