Swift Foundation日历nextDate()产生奇怪的结果

时间:2019-02-26 13:45:23

标签: swift calendar foundation

我认为这是我去年6月向Apple报告的错误(错误号41023217),但没有得到答复。欢迎任何见识。

摘要:

前后扫描匹配月份的日期会产生奇怪的结果。前向扫描似乎无法正确处理夏令时。向后扫描会产生有时看似根本错误的结果。

复制步骤:

在终端中启动快速REPL并运行以下代码:

import Foundation
var now = Date()
var cal = Calendar.current
var comp = DateComponents()
print("Scanning forward")
for monthNo in 1...12 {
    comp.setValue(monthNo, for: .month)
    let nextDate = cal.nextDate(after: now, matching: comp, matchingPolicy: .strict, repeatedTimePolicy: .first, direction: .forward)
    print("Month: ", monthNo, ", next date: ", nextDate)
}
print("Scanning backward")
for monthNo in 1...12 {
    comp.setValue(monthNo, for: .month)
    let nextDate = cal.nextDate(after: now, matching: comp, matchingPolicy: .strict, repeatedTimePolicy: .first, direction: .backward)
    print("Month: ", monthNo, ", next date: ", nextDate)
}

预期结果:

具有对应月份值的下一个日期,用于向前搜索。 用于后退搜索的具有最近月份值的最近日期(或至少具有相应月份值的最近范围的开始)。

实际结果:

Scanning forward
Month:  1 , next date:  Optional(2020-01-01 00:00:00 +0000)
Month:  2 , next date:  Optional(2020-02-01 00:00:00 +0000)
Month:  3 , next date:  Optional(2019-03-01 00:00:00 +0000)
Month:  4 , next date:  Optional(2019-03-31 23:00:00 +0000)
Month:  5 , next date:  Optional(2019-04-30 23:00:00 +0000)
Month:  6 , next date:  Optional(2019-05-31 23:00:00 +0000)
Month:  7 , next date:  Optional(2019-06-30 23:00:00 +0000)
Month:  8 , next date:  Optional(2019-07-31 23:00:00 +0000)
Month:  9 , next date:  Optional(2019-08-31 23:00:00 +0000)
Month:  10 , next date:  Optional(2019-09-30 23:00:00 +0000)
Month:  11 , next date:  Optional(2019-11-01 00:00:00 +0000)
Month:  12 , next date:  Optional(2019-12-01 00:00:00 +0000)
Scanning backward
Month:  1 , next date:  Optional(2019-01-05 00:00:00 +0000)
Month:  2 , next date:  Optional(2018-02-01 01:00:00 +0000)
Month:  3 , next date:  Optional(2018-03-02 23:00:00 +0000)
Month:  4 , next date:  Optional(2018-03-31 23:00:00 +0000)
Month:  5 , next date:  Optional(2018-05-02 23:00:00 +0000)
Month:  6 , next date:  Optional(2018-05-31 23:00:00 +0000)
Month:  7 , next date:  Optional(2018-07-01 23:00:00 +0000)
Month:  8 , next date:  Optional(2018-08-31 22:00:00 +0000)
Month:  9 , next date:  Optional(1970-08-31 23:00:00 +0000)
Month:  10 , next date:  Optional(2018-10-03 00:00:00 +0000)
Month:  11 , next date:  Optional(2018-11-01 00:00:00 +0000)
Month:  12 , next date:  Optional(2018-12-31 23:59:59 +0000)

2 个答案:

答案 0 :(得分:0)

我认为您误用了匹配政策和重复时间政策。

但是,如果您希望通过Calendar获得期望 结果,则可以使用 以下代码

// Import Foundation to use 'Calendar' and 'Date' classes and structures  
import Foundation

/// Setting the current user calendar
let cal = Calendar.autoupdatingCurrent

/// Saving the current date
let now = Date()

print("Forward scanning... ->")
for i in 1...12 {
    /// Storing result
    let date = cal.date(byAdding: .month, value: i, to: now)
    // Print result
    print("Mounth: \(i), date: \(date!.debugDescription)")
}

print("\nBackward scanning... ->")
for i in 1...12 {
    /// Storing result << please take note of the second argument>>>
    let date = cal.date(byAdding: .month, value: -i, to: now)
    // Print result
    print("Mounth: \(i), date: \(date!.debugDescription)")
}

使用date(byAdding: 'Calendar.Component', value: 'Int', to: 'Date')时,日历按字面月份的偏移量进行搜索

答案 1 :(得分:0)

您可以进一步限定DateComponents,我相信您会得到想要的值:

var comp = DateComponents(calendar: cal, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 0)

因此:

let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .short

let now = Date()
let calendar = Calendar.current
var components = DateComponents(calendar: calendar, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 0)

print("Scanning forward")
for monthNo in 1...12 {
    components.setValue(monthNo, for: .month)
    let nextDate = calendar.nextDate(after: now, matching: components, matchingPolicy: .strict, repeatedTimePolicy: .first, direction: .forward)
    print("Month: ", monthNo, ", next date: ", formatter.string(from: nextDate!))
}

print("Scanning backward")
for monthNo in 1...12 {
    components.setValue(monthNo, for: .month)
    let nextDate = calendar.nextDate(after: now, matching: components, matchingPolicy: .strict, repeatedTimePolicy: .first, direction: .backward)
    print("Month: ", monthNo, ", next date: ", formatter.string(from: nextDate!))
}

产生:

  

向前扫描
  月:1,下一个日期:1/1 / 20,12:00 AM
  月:2,下一个日期:20/1 / 20,12:00 AM
  月:3,下一个日期:19/1/19上午12:00
  月:4,下一个日期:19/4 / 1,12:00 AM
  月:5,下一个日期:19/5 / 1,12:00 AM
  月:6日,下一个日期:19年6月1日,上午12:00
  月:7日,下一个日期:19年7月1日,上午12:00
  月:8日,下一个日期:19年8月1日,上午12:00
  月:9,下一个日期:19/1 / 19,12:00 AM
  月:10,下一个日期:19/10/1/19,上午12:00
  月:11日,下一个日期:19/11/1/19上午12:00
  月:12,下一个日期:19/12/1/19,上午12:00
  向后扫描
  月:1,下一个日期:19-1-1 / 19上午12:00
  月:2,下一个日期:19/2 / 1,12:00 AM
  月:3日,下一个日期:18年3月1日,上午12:00
  月:4,下一个日期:18/4/1,上午12:00
  月:5日,下一个日期:18年5月1日,上午12:00
  月:6日,下一个日期:2018年6月1日,上午12:00
  月:7日,下一个日期:18年7月1日,上午12:00
  月:8日,下一个日期:18年8月1日,上午12:00
  月:9日,下一个日期:18年9月1日,上午12:00
  月:10,下一个日期:18/10/1 / 18,12:00 AM
  月:11日,下一个日期:18/11/1/18上午12:00
  月:12,下一个日期:18/12/1/18上午12:00