【问题标题】:How to get all days in a month that are a specific weekday?如何获取一个月中特定工作日的所有日子?
【发布时间】:2017-06-17 02:22:29
【问题描述】:

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

【问题讨论】:

    标签: ios objective-c calendar nscalendar


    【解决方案1】:

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

    一个DateComponents也有一个weekdayOrdinal属性,代表“the position of the weekday within the next larger calendar unit, such as the month. For example, 2 is the weekday ordinal unit for the second Friday of the month.

    所以让我们为 2017 年 6 月的某个星期六初始化一个 DateComponents。如果您不关心时间,通常最好指定中午的时间,因为 midnight (the default time of day) can cause problems in some time zones on some days

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

    【讨论】:

      【解决方案2】:

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

          //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"
      

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-06
        • 1970-01-01
        • 2019-05-14
        • 1970-01-01
        相关资源
        最近更新 更多