NSDate返回错误的周数

时间:2015-12-21 18:20:41

标签: swift nsdate nsdateformatter

我有以下代码:

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))中的日期返回dec 27, 2015, 7:16PM 这是正确的(下周日)但是,如果我尝试返回该日期的周数,则返回1,而这应该是53.如何获得正确的周数?

4 个答案:

答案 0 :(得分:8)

根据 Apple开发者技术支持

  

2015年12月27日是第52周,而不是第53周。2015年第53周的第一天是12月28日。

     

无论如何,你的getWeek()函数返回的值与ISO 8601不匹配是正确的。原因是你使用的是NSCalendarIdentifierGregorian而不是NSCalendarIdentifierISO8601。有/很多/不同的方法来进行一周的计算。如果你愿意,我可以进入血腥细节,但这里的'带回家'信息是,如果你想要ISO 8601周计算,你应该使用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日历。 (很奇怪)

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

请记住ISO周和美国周编号不同!如果您查看上面提到的维基百科文章,请进一步阅读“其他周编号系统”。因此,必须有一个设置来控制美国与ISO周。

答案 3 :(得分:0)

我已经使用小修补程序编译程序,并将日历更改为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)))