In my app I need to get the previous 4am, not the 4am of the current date.
For example:
在我的应用程序中,我需要获取前一个凌晨4点,而不是当前日期的凌晨4点。例如:
- if it's
March 05, 10:00 am
then I should expect to get back:March 05, 4:00 am
- 如果它是3月5日上午10:00,那么我应该期待回来:3月5日凌晨4:00
- if it's
March 05, 02:00 am
then I should expect to get back:March 04, 4:00 am
- 如果它是3月05日凌晨02:00,那么我应该期待回来:3月4日凌晨4:00
To achieve that I'm using Calendar.nextDate
. It works well for everyday of the month except the last day of each month.
为了实现这一点,我正在使用Calendar.nextDate。除了每个月的最后一天,它适用于本月的每日。
This is an example of the happy path, 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 the 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 it a bug in Apple's code, should I report it? or am I using this wrong?
If it's an Apple bug, is there another way of achieving what I need in the meantime?
知道为什么会这样吗?它是Apple的代码中的错误,我应该报告吗?或者我使用这个错误?如果它是Apple的bug,那么在此期间还有另一种方法可以实现我需要的东西吗?
Update:
After looking at some Swift source code, I noticed that the issue is not with the Calendar.nextDate()
function specifically. nextDate()
uses Calendar.enumerateDates()
and that's where the real issue is. I couldn't find the source code for that function though. This is the same bug using Calendar.enumerateDates()
:
在查看了一些Swift源代码之后,我注意到问题不在于Calendar.nextDate()函数。 nextDate()使用Calendar.enumerateDates(),这就是真正的问题所在。我找不到该功能的源代码。这是使用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's Calendar.enumerateDates gives incorrect result when starting on February
此外,这是一个类似的问题:Swift的Calendar.enumerateDates在2月开始时给出不正确的结果
1 个解决方案
#1
3
This does appear to be a bug that should be reported to Apple. Be sure you include a runnable test app demonstrating the issue. Note that this bug only appears in iOS. In macOS (at least a macOS playground), the code works as expected.
这似乎是一个应该向Apple报告的错误。确保您包含一个可运行的测试应用程序来演示该问题。请注意,此错误仅出现在iOS中。在macOS(至少是一个macOS playground)中,代码按预期工作。
In the meantime there is a fairly simple workaround.
与此同时,有一个相当简单的解决方法。
Change your code to use .forward
instead of .backward
. This will give the next date instead of the previous date. There does not seem to be any bugs going in that direction. Then use:
将代码更改为使用.forward而不是.backward。这将给出下一个日期而不是上一个日期。似乎没有任何错误朝那个方向发展。然后使用:
Calendar.current.date(byAdding: .day, value: -1, date: result)
to get your desired result by going back one day.
通过回去一天得到你想要的结果。
#1
3
This does appear to be a bug that should be reported to Apple. Be sure you include a runnable test app demonstrating the issue. Note that this bug only appears in iOS. In macOS (at least a macOS playground), the code works as expected.
这似乎是一个应该向Apple报告的错误。确保您包含一个可运行的测试应用程序来演示该问题。请注意,此错误仅出现在iOS中。在macOS(至少是一个macOS playground)中,代码按预期工作。
In the meantime there is a fairly simple workaround.
与此同时,有一个相当简单的解决方法。
Change your code to use .forward
instead of .backward
. This will give the next date instead of the previous date. There does not seem to be any bugs going in that direction. Then use:
将代码更改为使用.forward而不是.backward。这将给出下一个日期而不是上一个日期。似乎没有任何错误朝那个方向发展。然后使用:
Calendar.current.date(byAdding: .day, value: -1, date: result)
to get your desired result by going back one day.
通过回去一天得到你想要的结果。