【问题标题】:How to get dates for every thursday or other day of week in specific month?如何获取特定月份的每个星期四或一周中的其他日期的日期?
【发布时间】:2017-05-03 12:51:34
【问题描述】:

我想获取每周特定日期的日期。

假设我有一个约会:2017-04-13。这是四月,4 月 13 日是Thursday。我需要得到四月份的每个日期,即Thursday

我该怎么做?

输出应该是:2017-04-062017-04-132017-04-202017-04-27

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    短解:

    // 获取当前日历和当前日期 让日历 = Calendar.current 现在让 = 日期() // 获取年、月、工作日和工作日序号的当前日期组件 var components = calendar.dateComponents([.year, .month, .weekdayOrdinal, .weekday], from: now) // 获取该月特定工作日的范围(出现次数) 让 range = calendar.range(of: .weekdayOrdinal, in: .month, for: now)! // 遍历范围,将组件设置为适当的工作日序号并获取日期 对于 range.lowerBound 中的序数..

    请注意,print 始终以 UTC 格式打印日期。

    编辑:

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

    这是一个可行的选择。它检查日期是否超出月份范围

    // 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)!)
    }
    

    【讨论】:

      【解决方案2】:

      试试这个游乐场:

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

      【讨论】:

        【解决方案3】:

        这段代码完成了这项工作。我添加了一些日志以了解其背后的一些逻辑。 你可以随意设置dateInit,剩下的代码会查找同年同月同一个工作日的所有日子。

        我打印了两个版本的日期表示(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 标志单元,但枚举在第一次出现时停止,没有搜索很长时间为什么,我想出了只有月份和工作日标志让它工作。也许我错过了一些小问题。

        编辑: 在 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)")
        })
        

        【讨论】:

          【解决方案4】:

          我会为任何给定的时间跨度为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
              }
          }
          

          请注意,我破解它的速度可能相当快。我相信这可以更迅速地表达出来。在实际生产代码中,我也会尝试从中消除所有 !

          用法:

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

          【讨论】:

            【解决方案5】:

            按照评论中的建议。查看更新的代码。随工作日更新

            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)
            

            【讨论】:

            • 我建议let date2 = calendar.date(from: dateComponents as DateComponents); if calendar.component(.weekday, from: date2!) == 5 { numberOfSundays += 1; let dateThu = thuFormatter.string(from: date2!); dateArray.append(dateThu)} 而不是使用NSDateFormatter 和可能根据语言而改变的字符串比较。如果只是将其转换为DateComponents,请避免使用NSDateComponents,并使用Calendar 而不是NSCalendar,全部用于Swift 3。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-19
            • 2014-07-24
            • 1970-01-01
            • 1970-01-01
            • 2014-06-26
            相关资源
            最近更新 更多