获取给定 ISO 8601 日历年的周数
Get number of weeks for a given ISO 8601 calendar year
我需要根据 ISO 周系统 (ISO8601) 创建一个函数来计算 swift 中给定年份的周数。我需要这个数字作为 Int。首先,我想我需要为 12 月 31 日制作一个 NSDate,然后问一下现在是哪一周,然后我意识到有时 12 月 31 日是在下一年的第 1 周(例如 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)
但无论我投入哪一年,它都给了我 53 周。作为参考,2004 年有 53 周,2005 年有 52 周
为Swift工作 3:
let weekRange = NSCalendar.current.range(of: .weekOfYear, in: .yearForWeekOfYear, for: Date())
print("\(weekRange?.count)")
您必须在 Date() 中指定年份,它会为您提供全年的周数。
希望对您有所帮助!
一个简单的公式来确定一年中的周数
ISO 日历可以在 Long and Short ISO Calendar Years:
中找到
An ISO calendar year y is long (contains 53 weeks) if:
- p(y) modulo 7 = 4
or if:
- p(y–1) modulo 7 = 3
with:
- p(y) = y + floor(y/4) – floor(y/100) + floor(y/400)
请注意 Wikipedia: Weeks per year 中的版本似乎
要有一个小错误,"if p(year) = 5" 应该是 "if p(year) = 4".
这是 Swift 中的实现:
func weeks(in year: Int) -> Int {
func p(_ year: Int) -> Int {
return (year + year/4 - year/100 + year/400) % 7
}
return (p(year) == 4 || p(year-1) == 3) ? 53 : 52
}
测试:
print(weeks(in: 2015)) // 53
print(weeks(in: 2016)) // 52
let longYears = (2000...2100).filter({ weeks(in: [=11=]) == 53 })
print(longYears)
// [2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065, 2071, 2076, 2082, 2088, 2093, 2099]
这与维基百科文章中给出的列表一致。
重新编辑:您尝试的代码几乎是正确的。
正如@vadian 在评论中已经说过的那样,它应该是
let weekRange = calendarr.range(of: .weekOfYear, in: .yearForWeekOfYear, for: datumet!)
此外,1月1日可能属于之前的 ISO年份
(例如 2016 年)。选择给定年份的 1 月 4 日和 12 月 28 日之间的任何一天都可以解决该问题。
经过进一步的简化,得到以下结果
方法(基于):
func weeks(in year: Int) -> Int {
let cal = Calendar(identifier: .iso8601)
let date = DateComponents(calendar: cal, year: year, month: 2, day: 1).date!
let weeksRange = cal.range(of: .weekOfYear, in: .yearForWeekOfYear, for: date)!
return weeksRange.count
}
产生与上述函数相同的结果。
import Foundation
extension Date {
var lastDayOfMonth: Date {
return set(dayOfMonth: Calendar.autoupdatingCurrent.range(of: .day, in: .month, for: self)!.count)
}
func set(dayOfMonth: Int) -> Date {
let calendar = Calendar.autoupdatingCurrent
var components = calendar.dateComponents([.month, .year], from: self)
components.day = dayOfMonth
return calendar.date(from: components)!
}
func set(month: Int) -> Date {
let calendar = Calendar.autoupdatingCurrent
var components = calendar.dateComponents([.year], from: self)
components.month = month
return calendar.date(from: components)!
}
var weekNumber: Int {
return Calendar.autoupdatingCurrent.component(.weekOfYear, from: self)
}
var numberOfWeeksInYear: Int {
let weekNumber = set(month: 12).lastDayOfMonth.weekNumber
return weekNumber == 1 ? 52 : weekNumber
}
}
我需要根据 ISO 周系统 (ISO8601) 创建一个函数来计算 swift 中给定年份的周数。我需要这个数字作为 Int。首先,我想我需要为 12 月 31 日制作一个 NSDate,然后问一下现在是哪一周,然后我意识到有时 12 月 31 日是在下一年的第 1 周(例如 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)
但无论我投入哪一年,它都给了我 53 周。作为参考,2004 年有 53 周,2005 年有 52 周
为Swift工作 3:
let weekRange = NSCalendar.current.range(of: .weekOfYear, in: .yearForWeekOfYear, for: Date())
print("\(weekRange?.count)")
您必须在 Date() 中指定年份,它会为您提供全年的周数。
希望对您有所帮助!
一个简单的公式来确定一年中的周数 ISO 日历可以在 Long and Short ISO Calendar Years:
中找到An ISO calendar year y is long (contains 53 weeks) if:
- p(y) modulo 7 = 4
or if:
- p(y–1) modulo 7 = 3
with:
- p(y) = y + floor(y/4) – floor(y/100) + floor(y/400)
请注意 Wikipedia: Weeks per year 中的版本似乎 要有一个小错误,"if p(year) = 5" 应该是 "if p(year) = 4".
这是 Swift 中的实现:
func weeks(in year: Int) -> Int {
func p(_ year: Int) -> Int {
return (year + year/4 - year/100 + year/400) % 7
}
return (p(year) == 4 || p(year-1) == 3) ? 53 : 52
}
测试:
print(weeks(in: 2015)) // 53
print(weeks(in: 2016)) // 52
let longYears = (2000...2100).filter({ weeks(in: [=11=]) == 53 })
print(longYears)
// [2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065, 2071, 2076, 2082, 2088, 2093, 2099]
这与维基百科文章中给出的列表一致。
重新编辑:您尝试的代码几乎是正确的。 正如@vadian 在评论中已经说过的那样,它应该是
let weekRange = calendarr.range(of: .weekOfYear, in: .yearForWeekOfYear, for: datumet!)
此外,1月1日可能属于之前的 ISO年份 (例如 2016 年)。选择给定年份的 1 月 4 日和 12 月 28 日之间的任何一天都可以解决该问题。
经过进一步的简化,得到以下结果
方法(基于
func weeks(in year: Int) -> Int {
let cal = Calendar(identifier: .iso8601)
let date = DateComponents(calendar: cal, year: year, month: 2, day: 1).date!
let weeksRange = cal.range(of: .weekOfYear, in: .yearForWeekOfYear, for: date)!
return weeksRange.count
}
产生与上述函数相同的结果。
import Foundation
extension Date {
var lastDayOfMonth: Date {
return set(dayOfMonth: Calendar.autoupdatingCurrent.range(of: .day, in: .month, for: self)!.count)
}
func set(dayOfMonth: Int) -> Date {
let calendar = Calendar.autoupdatingCurrent
var components = calendar.dateComponents([.month, .year], from: self)
components.day = dayOfMonth
return calendar.date(from: components)!
}
func set(month: Int) -> Date {
let calendar = Calendar.autoupdatingCurrent
var components = calendar.dateComponents([.year], from: self)
components.month = month
return calendar.date(from: components)!
}
var weekNumber: Int {
return Calendar.autoupdatingCurrent.component(.weekOfYear, from: self)
}
var numberOfWeeksInYear: Int {
let weekNumber = set(month: 12).lastDayOfMonth.weekNumber
return weekNumber == 1 ? 52 : weekNumber
}
}