获取给定 ISO 8601 日历年的周数

Kla*_*und 5 calendar date iso8601 nsdate swift

我需要创建一个函数,根据 ISO 周系统(ISO8601)在 Swift 中计算给定年份的周数。我需要这个数字作为 Int。首先,我想我需要制定NSDate12 月 31 日的日期,然后询问那是哪一周。然后我意识到,有时 12 月 31 日位于下一年的第一周(例如,2014 年 12 月 31 日)。

有人知道有办法做到这一点吗?

我试过:

var calendarr = NSCalendar(calendarIdentifier: NSCalendar.Identifier.ISO8601)!
var monday = "01-01-2005"

var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"
var datumet = dateFormatter.date(from: monday)
var weekRange = calendarr.range(of: .weekOfYear, in: .year, for: datumet!)
var weeksCount = weekRange.length

print("this many weeks", weeksCount)
Run Code Online (Sandbox Code Playgroud)

然而,无论我输入哪一年,它都会给我 53 周。作为参考,2004 年有 53 周,2005 年有 52 周。

Mar*_*n R 6

可以在长和短 ISO 日历年中找到用于确定 ISO 日历一年\n周数的简单公式

\n
\n

如果满足以下条件,则 ISO 日历年 y 很长(包含 53 周):

\n
    \n
  • p(y) 模 7 = 4
    \nor 如果:
  • \n
  • p(y\xe2\x80\x931) 模 7 = 3
    \n其中:
  • \n
  • p(y) = y + 楼层(y/4) \xe2\x80\x93 楼层(y/100) + 楼层(y/400)
  • \n
\n
\n

请注意,维基百科中的版本:每周周似乎有一个小错误,“if p(year) = 5”应该是“if p(year) = 4”。

\n

这是 Swift 中的一个实现:

\n
func weeks(in year: Int) -> Int {\n    func p(_ year: Int) -> Int {\n        return (year + year/4 - year/100 + year/400) % 7\n    }\n    return (p(year) == 4 || p(year-1) == 3) ? 53 : 52\n}\n
Run Code Online (Sandbox Code Playgroud)\n

测试:

\n
print(weeks(in: 2015)) // 53\nprint(weeks(in: 2016)) // 52\n\nlet longYears = (2000...2100).filter({ weeks(in: $0) == 53 })\nprint(longYears)\n// [2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065, 2071, 2076, 2082, 2088, 2093, 2099]\n
Run Code Online (Sandbox Code Playgroud)\n

这与维基百科文章中给出的列表一致。

\n
\n

更新

\n

关于您添加到问题中的代码块:您的代码几乎是正确的。

\n

正如@vadian在评论中已经说过的那样,应该是

\n
let weekRange = calendarr.range(of: .weekOfYear, in: .yearForWeekOfYear, for: datumet!)\n
Run Code Online (Sandbox Code Playgroud)\n

此外,1 月 1 日可能属于上一个ISO年份\n(例如 2016 年)。选择给定年份的 1 月 4 日到 12 月 28 日之间的任何一天都可以解决该问题。

\n

经过一些进一步的简化,给出了以下\n方法(基于Kevin Sabbe 的方法):

\n
func weeks(in year: Int) -> Int {\n    let cal = Calendar(identifier: .iso8601)\n    let date = DateComponents(calendar: cal, year: year, month: 2, day: 1).date!\n    let weeksRange = cal.range(of: .weekOfYear, in: .yearForWeekOfYear, for: date)!\n    return weeksRange.count\n}\n
Run Code Online (Sandbox Code Playgroud)\n

它产生与上面函数相同的结果。

\n

附录

\n

正如@Olex在评论中建议的那样,这甚至更好(\xe2\x80\x9cno 幻数 \'2\' 并保持在 \'week-of-year\' 计算范例 \xe2\x80\x9d):

\n
func weeks(in year: Int) -> Int {\n    let cal = Calendar(identifier: .iso8601)\n    let date = DateComponents(calendar: cal, weekday: 1, weekOfYear: 1, yearForWeekOfYear: year).date!\n    let weeksRange = cal.range(of: .weekOfYear, in: .yearForWeekOfYear, for: date)!\n    return weeksRange.count\n}\n
Run Code Online (Sandbox Code Playgroud)\n