如何获得每个星期四或特定月份的其他星期几?

我想每个星期都能得到某一天的date。

假设我有一个date: 2017-04-13 。 这是一个四月,而四月十三日是Thursday 。 我需要得到Thursday月份的每一个Thursday

我怎样才能做到这一点?

输出结果应该是: 2017-04-27

简而言之:

//获取当前日历和当前datelet calendar = Calendar.current let now = Date()//获取当前date组件的年,月,星期几和星期几序号var components = calendar.dateComponents([。year,.month, .weekdayOrdinal,.weekday],from:now)//获取月份中特定工作日的范围(出现次数)let range = calendar.range(of:.weekdayOrdinal,in:.month,for:now)! //通过范围循环,将组件设置为适当的星期几序号,并得到序号的date在range.lowerBound ..

请注意, printdate始终使用UTC。

编辑:

range(of: .weekdayOrdinal, in: .month不起作用,无论date如何,都返回1..<6

这是一个可行的select。 它检查date是否超过月份

 // Get current calendar and date for 2017/4/13 let calendar = Calendar.current let april13Components = DateComponents(year:2017, month:4, day:13) let april13Date = calendar.date(from: april13Components)! // Get the current date components for year, month, weekday and weekday ordinal var components = calendar.dateComponents([.year, .month, .weekdayOrdinal, .weekday], from: april13Date) // Loop thru the range, set the components to the appropriate weekday ordinal and get the date for ordinal in 1..<6 { // maximum 5 occurrences components.weekdayOrdinal = ordinal let date = calendar.date(from: components)! if calendar.component(.month, from: date) != components.month! { break } print(calendar.date(from: components)!) } 

试试这个操场:

 import UIKit let dateString = "2017-04-13" let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let referenceDate = dateFormatter.date(from: dateString)! let calendar = Calendar.current let firstDayComponents = calendar.dateComponents([.year, .month], from: referenceDate) let monthFirst = calendar.date(from: firstDayComponents)! let weekDay = calendar.component(.weekday, from: referenceDate) var oneDay = DateComponents() oneDay.day = 1 var checkDate = monthFirst while calendar.component(.month, from: checkDate) == calendar.component(.month, from: referenceDate) { if calendar.component(.weekday, from: checkDate) == weekDay { let thisDay = dateFormatter.string(from: checkDate) print(thisDay) } checkDate = calendar.date(byAdding: oneDay, to: checkDate)! } 

这段代码完成了这项工作。 我添加了一些日志来了解它背后的一些逻辑。 您可以根据需要设置dateInit ,其余代码将查找同一个工作日在同一个月的所有date。

我打印两个版本的date表示( NSDate对象和NSString对象),与时区和“这不是同一天”的呼声问题。

它使用了enumerateDatesStartingAfterDate:matchingComponents:options:usingBlock:

 NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; NSString *dateStr = @"2017-04-13"; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd"]; NSDate *dateInit = [dateFormatter dateFromString:dateStr]; NSLog(@"dateInit: %@", dateInit); NSDateComponents *componentsToMatch = [calendar components:(NSCalendarUnitMonth|NSCalendarUnitWeekday) fromDate:dateInit]; NSDate *startOfMonth = [calendar dateFromComponents:[calendar components:(NSCalendarUnitYear|NSCalendarUnitMonth) fromDate:dateInit]]; NSLog(@"StartOfTheMonth: %@", startOfMonth); NSArray *daysToFind = @[@"2017-04-06", @"2017-04-13", @"2017-04-20", @"2017-04-27"]; //According to author NSLog(@"DaysToFind: %@", daysToFind); NSMutableArray *allDaysInMonthMatchingWeekDay = [[NSMutableArray alloc] init]; [calendar enumerateDatesStartingAfterDate:startOfMonth matchingComponents:componentsToMatch options:NSCalendarMatchStrictly usingBlock:^(NSDate * _Nullable date, BOOL exactMatch, BOOL * _Nonnull stop) { NSLog(@"DateBlock: %@", date); [allDaysInMonthMatchingWeekDay addObject:date]; }]; NSLog(@"allDaysInMonthMatchingWeekDay: %@",allDaysInMonthMatchingWeekDay); for (NSDate *aDate in allDaysInMonthMatchingWeekDay) { NSLog(@"Found: %@", [dateFormatter stringFromDate:aDate]); } 

日志:

 $>dateInit: 2017-04-12 22:00:00 +0000 $>StartOfTheMonth: 2017-03-31 22:00:00 +0000 $>DaysToFind: ( "2017-04-06", "2017-04-13", "2017-04-20", "2017-04-27" ) $>DateBlock: 2017-04-05 22:00:00 +0000 $>DateBlock: 2017-04-12 22:00:00 +0000 $>DateBlock: 2017-04-19 22:00:00 +0000 $>DateBlock: 2017-04-26 22:00:00 +0000 $>allDaysInMonthMatchingWeekDay: ( "2017-04-05 22:00:00 +0000", "2017-04-12 22:00:00 +0000", "2017-04-19 22:00:00 +0000", "2017-04-26 22:00:00 +0000" ) $>Found: 2017-04-06 $>Found: 2017-04-13 $>Found: 2017-04-20 $>Found: 2017-04-27 

注意:对于componentsToMatch ,我试图设置Year / Month / WeekDay标志单元,但枚举停在第一次发生,没有search多久为什么,我想出了只有月和星期几的标志,以使其工作。 也许是我错过了一些小问题。

编辑:在Swift 3(它的工作原理,但因为我是一个Objective-C的开发人员,而不是一个Swift的,它可能有问题,如包装/解包等)

 let calendar = NSCalendar.init(calendarIdentifier: .gregorian) let dateStr = "2017-04-13" let dateFormatter = DateFormatter.init() dateFormatter.dateFormat = "yyyy-MM-dd" let dateInit = dateFormatter.date(from: dateStr)! print("dateInit: \(dateInit)") let componentsToMatch = calendar?.components([.month,.weekday], from: dateInit) let startOfMonth = calendar?.date(from: (calendar?.components([.year,.month], from: dateInit))!) print("StartOfTheMonth:\(startOfMonth)") calendar?.enumerateDates(startingAfter: startOfMonth!, matching: componentsToMatch!, options: .matchStrictly, using: { (date, extactMatch, stop) in print("DateBlock: \(date)") }) 

我会为任何给定的时间范围写一个Calendar的扩展,并使用枚举来命名工作日

 enum WeekDay: Int { case sunday = 1 case monday case tuesday case wednesday case thursday case friday case saturday } struct TimeSpan { let startDate: Date let endDate: Date } extension Calendar { func allOccurrenceOf(day: WeekDay, in timeSpan:TimeSpan) -> [Date] { let startDateWeekDay = Int(self.component(.weekday, from: timeSpan.startDate)) let desiredDay = day.rawValue let offset = (desiredDay - startDateWeekDay + 7) % 7 let firstOccurrence = self.startOfDay(for:self.date(byAdding: DateComponents(day:offset), to: timeSpan.startDate)!) guard firstOccurrence.timeIntervalSince1970 < timeSpan.endDate.timeIntervalSince1970 else { return [] } var filtered = [firstOccurrence] while true { let nextDate = self.date(byAdding: DateComponents(day: 7), to: filtered.last!)! if nextDate < timeSpan.endDate { filtered.append(nextDate) break } } return filtered } } 

要小心,我砍了这可能相当快。 我相信这可以更迅速地expression出来。 在真正的生产代码中,我也试图消除所有的! 从中。

用法:

 let tuesdays = Calendar.autoupdatingCurrent.allOccurrenceOf(day: .tuesday, in: TimeSpan(startDate: Date(), endDate: Calendar.autoupdatingCurrent.date(byAdding: DateComponents(month:1), to: Date())!)) 

正如评论中的build议。 看到更新的代码。 更新周一天

 func getNumberOfDaysInMonth (month : Int , Year : Int, weekday: Int) -> [String]{ let dateComponents = NSDateComponents() dateComponents.year = Year dateComponents.month = month let calendar = Calendar.current let date = calendar.date(from: dateComponents as DateComponents) let range = calendar.range(of: .day, in: .month, for: date!) let numDays:Int = (range?.upperBound)! let thuFormatter = DateFormatter() var dateArray:[String] = [String]() thuFormatter.dateFormat = "yyyy-MM-dd" for day in 1...numDays { dateComponents.day = day let date2 = calendar.date(from: dateComponents as DateComponents) print(calendar.component(.weekday, from: date2!)) if calendar.component(.weekday, from: date2!) == weekday { let dateThu = thuFormatter.string(from: date2!) dateArray.append(dateThu) } } return dateArray } 

然后像这样称呼它

 let myThu:[String] = getNumberOfDaysInMonth(month: 4, Year: 2017,weekday: 3) print(myThu)