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

jyztefdp  于 2023-02-18  发布在  Swift
关注(0)|答案(3)|浏览(142)

我需要创建一个函数,用于根据ISO周系统计算swift中给定年份的周数(ISO8601)。我需要的号码作为一个国际。首先,我想我需要做一个NSDate为12月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)

但不管我放进哪一年,它都给了我53周。作为参考,2004年有53周,2005年有52周

u3r8eeie

u3r8eeie1#

Long and Short ISO Calendar Years中可以找到一个简单的公式来确定ISO日历中一年的周数:
如果满足以下条件,则ISO日历年y较长(包含53周):

  • p(y)模7 = 4

或者如果:

  • p(y-1)模7 = 3

与:

  • p(y)= y+下限(y/4)-下限(y/100)+下限(y/400)

请注意维基百科中的版本:周每年似乎有一个小错误,"如果p(年)= 5"应该是"如果p(年)= 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: $0) == 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日之间的任何一天都可以解决这个问题。
进一步简化后,给出以下方法(基于Kevin Sabbe's approach):

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
}

其产生与上述函数相同的结果。

  • 附录:* 正如@Olex在评论中所建议的,这甚至更好("没有幻数" 2 ",保持在"一年中的一周"计算的范式中"):
func weeks(in year: Int) -> Int {
    let cal = Calendar(identifier: .iso8601)
    let date = DateComponents(calendar: cal, weekday: 1, weekOfYear: 1, yearForWeekOfYear: year).date!
    let weeksRange = cal.range(of: .weekOfYear, in: .yearForWeekOfYear, for: date)!
    return weeksRange.count
}
lf5gs5x2

lf5gs5x22#

为Swift工作3:

let weekRange = NSCalendar.current.range(of: .weekOfYear, in: .yearForWeekOfYear, for: Date())

print("\(weekRange?.count)")

您必须在Date()中指定年份,它将为您提供全年的周数。
希望能有所帮助!

omjgkv6w

omjgkv6w3#

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
    }
}

相关问题