如何计算给定月份的周数?

问题描述 投票:0回答:6

在查看了一些关于 SO 的不同建议后,我无法确定为什么下面的功能不起作用。它似乎在某些月份返回 6,而在其他月份返回 5。当改变几周或几天时,效果非常好。

例如,尝试

weeksInMonth(8, forYear 2015) 

结果为 6。

我相信我对日历上“firstWeekday”属性的作用存在误解,但尚未找到 Apple 或在线的充分解释。

已尝试过 .WeekOfMonth 和 .WeekOfYear。再次找不到确切差异的解释。

如有任何建议,我们将非常欢迎。

func weeksInMonth(month: Int, forYear year: Int) -> Int?
{
    if (month < 1 || month > 12) { return nil }

    let dateString = String(format: "%4d/%d/01", year, month)
    let dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "yyyy/MM/dd"
    if let date = dateFormatter.dateFromString(dateString),
       let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
    {
        calendar.firstWeekday = 2 // Monday
        let weekRange = calendar.rangeOfUnit(.WeekOfMonth, inUnit: .Month, forDate: date)
        let weeksCount = weekRange.length
        return weeksCount
    }
    else
    {
        return nil
    }
}

更新:

抱歉我的问题不清楚。我正在尝试算出一个月中有多少周包含星期一。对于 8 月,这应该是 5。

swift
6个回答
8
投票

您的代码计算发生的周数(完整或部分) 在一个月。您显然想要的是星期一的数量 在给定的月份。与

NSDateComponents
,特别是与 您可以计算第一个
weekdayOrdinal
属性 (
weekdayOrdinal=1
) 和最后 (
weekdayOrdinal=-1
) 星期一 在一个月。然后计算周数的差异(并加一)。

Swift 2 中可能的实现:

func numberOfMondaysInMonth(month: Int, forYear year: Int) -> Int?
{
    let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    calendar.firstWeekday = 2 // 2 == Monday

    // First monday in month:
    let comps = NSDateComponents()
    comps.month = month
    comps.year = year
    comps.weekday = calendar.firstWeekday
    comps.weekdayOrdinal = 1
    guard let first = calendar.dateFromComponents(comps)  else {
        return nil
    }

    // Last monday in month:
    comps.weekdayOrdinal = -1
    guard let last = calendar.dateFromComponents(comps)  else {
        return nil
    }

    // Difference in weeks:
    let weeks = calendar.components(.WeekOfMonth, fromDate: first, toDate: last, options: [])
    return weeks.weekOfMonth + 1
}

注意: 负数

weekdayOrdinal
从月底开始倒数,这一点在文档中并不明显。观察到 确定特定年份阵亡将士纪念日的 NSDate 并由 Dave DeLong 确认)。


更新

Swift 3:

func numberOfMondaysInMonth(_ month: Int, forYear year: Int) -> Int? { var calendar = Calendar(identifier: .gregorian) calendar.firstWeekday = 2 // 2 == Monday // First monday in month: var comps = DateComponents(year: year, month: month, weekday: calendar.firstWeekday, weekdayOrdinal: 1) guard let first = calendar.date(from: comps) else { return nil } // Last monday in month: comps.weekdayOrdinal = -1 guard let last = calendar.date(from: comps) else { return nil } // Difference in weeks: let weeks = calendar.dateComponents([.weekOfMonth], from: first, to: last) return weeks.weekOfMonth! + 1 }
    

5
投票
实际上你的问题是:某个月有多少个星期一?

我的方法是计算该月的第一个星期一,这可以通过将 CalendarUnit

WeekdayOrdinal

 设置为 1 来完成。然后获取总天数并进行一些数学计算。

斯威夫特1.2

func mondaysInMonth(month: Int, forYear year: Int) -> Int? { if 1...12 ~= month { let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)! let components = NSDateComponents() components.weekday = 2 // Monday components.weekdayOrdinal = 1 components.month = month components.year = year if let date = calendar.dateFromComponents(components) { let firstDay = calendar.component(.CalendarUnitDay, fromDate: date) let days = calendar.rangeOfUnit(.CalendarUnitDay, inUnit:.CalendarUnitMonth, forDate:date).length return (days - firstDay) / 7 + 1 } } return nil }

斯威夫特2

func mondaysInMonth(month: Int, forYear year: Int) -> Int? { guard 1...12 ~= month else { return nil } let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)! let components = NSDateComponents() components.weekday = 2 // Monday components.weekdayOrdinal = 1 components.month = month components.year = year if let date = calendar.dateFromComponents(components) { let firstDay = calendar.component(.Day, fromDate: date) let days = calendar.rangeOfUnit(.Day, inUnit:.Month, forDate:date).length return (days - firstDay) / 7 + 1 } return nil }
    

1
投票

斯威夫特2

以下代码计算一个月中的周数。它不取决于该月的开始或结束日期。

func weeksInMonth(month: Int, year: Int) -> (Int)? { let calendar = NSCalendar.currentCalendar() let comps = NSDateComponents() comps.month = month+1 comps.year = year comps.day = 0 guard let last = calendar.dateFromComponents(comps) else { return nil } // Note: Could get other options as well let tag = calendar.components([.WeekOfMonth,.WeekOfYear, .YearForWeekOfYear,.Weekday,.Quarter],fromDate: last) return tag.weekOfMonth } // Example Usage: if let numWeeks = weeksInMonth(8,year: 2015) { print(numWeeks) // Prints 6 } if let numWeeks = weeksInMonth(12,year: 2015) { print(numWeeks) // Prints 5 }
    

0
投票
斯威夫特4+:

//-- Get number of weeks from calendar func numberOfWeeksInMonth(_ date: Date) -> Int { var calendar = Calendar(identifier: .gregorian) calendar.firstWeekday = 1 let weekRange = calendar.range(of: .weekOfMonth, in: .month, for: date) return weekRange!.count } //-- Implementation let weekCount = numberOfWeeksInMonth(Date)
    

0
投票
斯威夫特4+:

从您的组件生成日期:

let dateComponents = DateComponents.init(year: 2019, month: 5) let monthCurrentDayFirst = Calendar.current.date(from: dateComponents)! let monthNextDayFirst = Calendar.current.date(byAdding: .month, value: 1, to: monthCurrentDayFirst)! let monthCurrentDayLast = Calendar.current.date(byAdding: .day, value: -1, to: monthNextDayFirst)!

从日期检测周数:

let numberOfWeeks = Calendar.current.component(.weekOfMonth, from: monthCurrentDayLast)
    

0
投票
恕我直言,最简单的解决方案是

Calendar.current.range(of: .weekOfMonth, in: .month, for: date)
无需设置任何 

firstWeekday

 或使用 
NSDateComponents
.. 除了日期之外什么都没有。
仅供参考 
firstWeekday
 可能会导致意外行为,因为某些地区使用星期一作为一周的第一天,而不是星期日

© www.soinside.com 2019 - 2024. All rights reserved.