NSDate returns 错误的周数

NSDate returns wrong week Number

我有以下代码:

getWeek(addDays(Date, amount: 6))

func addDays(date: NSDate, amount: Int) -> NSDate {
    // calculation $additionalDays
    let additionalDays = amount
    // adding $additionalDays
    let components = NSDateComponents()
    components.day = additionalDays

    // important: NSCalendarOptions(0)
     let futureDate = NSCalendar.currentCalendar()
    .dateByAddingComponents(components, toDate: date, options: NSCalendarOptions(rawValue: 0))
    return futureDate!
}

func getWeek(today:NSDate)->Int? {
    let formatter = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    let myComponents = myCalendar.components(.WeekOfYear, fromDate: today)
    let weekNumber = myComponents.weekOfYear
   return weekNumber
}

日期 getWeek(addDays(Date, amount: 6)) returns dec 27, 2015, 7:16PM 这是正确的(下周日)但是,如果我尝试 return 那个日期的周数,它 returns 1 而这应该是 53。我怎样才能得到正确的周数?

这可能是 Apple 实施中的错误。 Apple 似乎认为 2015 年 12 月 27 日是 2016 年的第一周。但是,根据 ISO 周日期标准,它应该在第 53 周,因为 12 月 31 日是星期四。 (12 月 31 日星期三应视为第 1 周:https://en.wikipedia.org/wiki/ISO_week_date#Last_week)。

要解决此问题,您可能需要进行一些额外的计算。例如,您可以检查 .YearForWeekOfYear 以检查 2016 年第 1 周并从那里做出决定。

请注意 ISO 周和美国周编号不同!如果您查看上面提到的维基百科文章,请继续阅读直到 "Other week numbering systems"。因此必须有一个设置来控制美国周与 ISO 周。

我已经使您的程序通过小的修复进行编译,并将日历更改为 ISO。这为 2015 年提供了预期的结果,请与其他年份一起测试。

import Foundation

let now = NSDate()

func addDays(date: NSDate, amount: Int) -> NSDate {
    // calculation $additionalDays
    let additionalDays = amount
    // adding $additionalDays
    let components = NSDateComponents()
    components.day = additionalDays

    // important: NSCalendarOptions(0)
    let futureDate = NSCalendar.currentCalendar()
        .dateByAddingComponents(components, toDate: date, options: NSCalendarOptions(rawValue: 0))
    return futureDate!
}

func getWeek(today:NSDate)->Int {
    let formatter = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)!
    let myComponents = myCalendar.components(.WeekOfYear, fromDate: today)
    let weekNumber = myComponents.weekOfYear
    return weekNumber
}

print(getWeek(addDays(now, amount: 6)))

根据Apple 开发者技术支持

27 Dec 2015 is week 52, not week 53. The first day of week 53 in 2015 is 28 Dec.

Regardless, you’re correct that the value returned by your getWeek() function does not match ISO 8601. The reason for that is that you’re using NSCalendarIdentifierGregorian rather than NSCalendarIdentifierISO8601. There are /lots/ of different ways to do week-of-year calculations. I can go into the gory details if you’d like, but the ‘take home’ message here is that, if you want ISO 8601 week calculations, you should use NSCalendarIdentifierISO8601.

通过该更改 getWeek() 开始生成符合 ISO 8601 的结果。具体而言:

print(self.getWeek(self.dateFromFixedFormatString("2015-12-27 12:34")))
print(self.getWeek(self.dateFromFixedFormatString("2015-12-28 12:34")))

打印:

  • 52
  • 53

假设:

func dateFromFixedFormatString(dateStr: String) -> NSDate {
   let df = NSDateFormatter()
   df.locale = NSLocale(localeIdentifier: "en_US_POSIX")
   df.dateFormat = "yyyy-MM-dd HH:mm"
   return df.dateFromString(dateStr)!
}
func getWeek(today:NSDate) -> Int {
   let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)!
   let myComponents = myCalendar.components(.WeekOfYear, fromDate: today)
   let weekNumber = myComponents.weekOfYear
   return weekNumber
}

所以任何人说 GregorianCalendar 在我的代码中不起作用是正确的,应该专门使用 NSCalendarIdentifierISO8601。 NSCalendar.currentCalendar() 不会自动获取 ISO 日历。 (很奇怪)