如何获取一个月中特定工作日的所有日子?



如何根据给定的一天获取月份的实际日期?例如,我想检索2017年6月的所有日期,即星期六。我怎样才能做到这一点?示例代码将不胜感激,因为我为此挣扎了好几天。

DateComponents具有weekday属性,表示星期几。工作日(在基金会的公历中)编号为星期日的1,星期一的编号为2,...,星期六的编号为7。

DateComponents还具有weekdayOrdinal属性,表示"工作日在下一个较大的日历单位(如月份)中的位置。例如,2 是该月第二个星期五的工作日序数单位。

因此,让我们初始化 2017 年 6 月某个星期六的DateComponents。如果您不关心时间,通常最好指定中午时间,因为午夜(一天中的默认时间)在某些日子的某些时区可能会导致问题。

var components = DateComponents(era: 1, year: 2017, month: 06, hour: 12, weekday: 7)

让我们做一个日历。

var calendar = Calendar.autoupdatingCurrent

现在我们可以遍历所有可能的工作日序数。对于每个日期,我们将要求日历生成一个日期。然后我们要求日历将日期转换回年、月和日部分。

在公历中,有些月份有 5 个星期六,但大多数月份有 4 个星期六。因此,当我们要求第5个星期六时,我们可能会在下个月得到一个日期。发生这种情况时,我们希望禁止显示该日期。

for i in 1 ... 5 {
components.weekdayOrdinal = i
let date = calendar.date(from: components)!
let ymd = calendar.dateComponents([.year, .month, .day], from: date)
guard ymd.month == components.month else { break }
print("(ymd.year!)-(ymd.month!)-(ymd.day!)")
}

输出:

2017-6-3
2017-6-10
2017-6-17
2017-6-24

Objective-C 版本:

NSDateComponents *components = [NSDateComponents new];
components.era = 1;
components.year = 2017;
components.month = 6;
components.hour = 12;
components.weekday = 7;
NSCalendar *calendar = NSCalendar.autoupdatingCurrentCalendar;
for (NSInteger i = 1; i <= 5; ++i) {
components.weekdayOrdinal = i;
NSDate *date = [calendar dateFromComponents:components];
NSDateComponents *ymd = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
if (ymd.month != components.month) { break; }
NSLog(@"%ld-%ld-%ld", (long)ymd.year, (long)ymd.month, (long)ymd.day);
}

这是使用称为enumerateDates的方法并使用Date扩展来解决calendar问题的另一种解决方案

//month in MM format, year in yyyy format and dayNumber as Int 1 for sunday, 7 for saturday
func datesWith(dayNumber:Int,month:String,year:String) -> [Date]
{
assert(dayNumber >= 1 && dayNumber <= 7, "Day number is wrong")
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date = dateFormatter.date(from: year + "-" + month + "-" + "01")
guard date != nil else {
return []
}
var resultDates : [Date] = []
//check if firstDay of month is desired weekday
if(Calendar.current.component(.weekday, from: date!) == dayNumber)
{
resultDates.append(date!)
}
Calendar.current.enumerateDates(startingAfter: date!, matching: DateComponents(weekday: dayNumber), matchingPolicy: Calendar.MatchingPolicy.nextTimePreservingSmallerComponents) { (currentDate, result, stop) in
if(currentDate! > date!.endOfMonth())
{
stop = true
return
}
resultDates.append(currentDate!)
}
return resultDates
}

外延

extension Date {
func startOfMonth() -> Date {
return Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: Calendar.current.startOfDay(for: self)))!
}
func endOfMonth() -> Date {
return Calendar.current.date(byAdding: DateComponents(month: 1, day: -1), to: self.startOfMonth())!
}
}

使用它

override func viewDidLoad() {
super.viewDidLoad()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
// Do any additional setup after loading the view, typically from a nib.
let datesArray = self.datesWith(dayNumber: 5, month: "06", year: "2017")
for currDate in datesArray {
debugPrint(dateFormatter.string(from: currDate))
}
}

输出

"2017-06-01"
"2017-06-08"
"2017-06-15"
"2017-06-22"
"2017-06-29"

希望这有帮助

最新更新