代码之家  ›  专栏  ›  技术社区  ›  aboodmufti

日历使用时,nextDate()的行为非常奇怪。向后指示方向。仅限当月最后一天

  •  9
  • aboodmufti  · 技术社区  · 7 年前

    在我的应用程序中,我需要获取之前的凌晨4点,而不是当前日期的凌晨4点。
    例如:

    • 如果是 March 05, 10:00 am 那么我应该回去了: March 05, 4:00 am
    • 如果是 March 05, 02:00 am 那么我应该回去了: March 04, 4:00 am

    为了实现我正在使用的 Calendar.nextDate 。除了每个月的最后一天之外,它在每个月的每一天都能正常工作。

    这是“快乐之路”的一个例子,它按预期工作:

    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)
    

    输出:

    date = "Mar 5, 2018 at 1:25 PM"
    result = "Mar 5, 2018 at 4:00 AM"
    

    这是黑暗悲伤之路的一个例子 不是 按预期行事:

    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)
    

    输出:

    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"
    

    知道为什么会这样吗?这是苹果代码中的错误吗?我应该报告吗?还是我用错了?
    如果这是一个苹果错误,有没有其他方法可以同时满足我的需求?

    更新时间:

    在查看了一些Swift源代码后,我注意到问题不在于 Calendar.nextDate() 具体功能。 nextDate() 使用 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
    }
    

    此外,这也是一个类似的问题: Swift's Calendar.enumerateDates gives incorrect result when starting on February

    1 回复  |  直到 7 年前
        1
  •  4
  •   rmaddy    7 年前

    这似乎是一个应该向苹果报告的bug。确保包含一个可运行的测试应用程序来演示该问题。 笔记 这个bug只出现在iOS中。在macOS(至少是macOS游戏场)中,代码按预期工作。

    与此同时,有一个相当简单的解决方法。

    更改要使用的代码 .forward 而不是 .backward 。这将给出下一个日期,而不是上一个日期。似乎没有任何错误朝这个方向发展。然后使用:

    Calendar.current.date(byAdding: .day, value: -1, date: result)
    

    回去一天,就能得到你想要的结果。