【问题标题】:How to calculate first NSDate of current week?如何计算本周的第一个 NSDate?
【发布时间】:2011-03-31 22:59:24
【问题描述】:

即:

  NSDate *firstDayOfWeek = [[NSDate date] firstDayOfWeek];

例如,今天是 8 月 19 日,我想从上面的代码行中获取 NSDate2010-08-15 12:00am。谢谢!

【问题讨论】:

标签: iphone cocoa-touch nsdate


【解决方案1】:

对于 Swift 4.1:

extension Date {
  var startOfWeek: Date? {
        let calendar = Calendar(identifier: .gregorian)
        return calendar.date(from: calendar.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))
    }
}

【讨论】:

    【解决方案2】:

    为什么这么复杂? :)

    func firstDateOfWeekWithDate(date: NSDate) -> NSDate {
    
        var beginningOfWeek: NSDate?
    
        calendar.rangeOfUnit(.WeekOfYear, startDate: &beginningOfWeek, interval: nil, forDate: date)
    
        return beginningOfWeek!
    
    }
    

    【讨论】:

    • 这是一个更简单的解决方案。我可以验证它比 Wolfgang 和 naixn 的解决方案效果更好。
    • 正确而准确。真的很完美。
    • 这是正确的做法。我登录只是为了给这个投票:)
    • 这正是 StackOverFlow 如此有用的原因。感谢您提供这个精确、非常简短和可靠的答案!
    【解决方案3】:

    这已经被回答了,但是作为Wolfgang has pointed out,在接受的答案中有一个错误。如果将第一个工作日设置为大于相关NSDate 的日期,则结果将不正确。这是一个适用于所有可能的firstWeekday 值的完整解决方案(示例使用星期一)。

    - (NSDate *)weekOfDate:(NSDate *)originalDate
    {
        NSCalendar *currentCal = [NSCalendar currentCalendar];
        [currentCal setFirstWeekday:2]; // Sun = 1, Mon = 2, etc.
    
        NSDateComponents *weekdayComponents = [currentCal components:NSCalendarUnitWeekday fromDate:originalDate];
    
        // Calculate the number of days to subtract and create NSDateComponents with them.
        NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init];
        NSInteger daysToSubtract = (([weekdayComponents weekday] - [currentCal firstWeekday]) + 7) % 7;
        [componentsToSubtract setDay:-1 * daysToSubtract];
    
        return [currentCal dateByAddingComponents:componentsToSubtract toDate:originalDate options:0];
    }
    

    【讨论】:

    • 有没有办法使用它来获取本周最后一天的NSDate
    【解决方案4】:

    最简单的解决方案:

    func firstDayOfWeek(date: NSDate) -> NSDate {
      let calendar = NSCalendar.currentCalendar()
      var dateComponents = calendar.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitWeekOfMonth, fromDate: date)
      dateComponents.weekday = 1
      return calendar.dateFromComponents(dateComponents)!
    }
    

    【讨论】:

    • 对我来说已经过去了一周:我完全按照上面的方式实现并通过了 date = NSDate();它应该在 8 月 17 日返回,它在 8 月 24 日返回。
    • 你可以试试.CaleandarUnitWeekOfYear | .CalendarUnitYearForWeekOfYear,而不是.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitWeekOfMonth。因为一个星期可能会被两个月或两年共享。 @cdf1982 , @Vassily
    • 这是错误的,您在重新编写日期时会丢失时区等信息。
    【解决方案5】:
    - (NSDate *)firstDateOfWeekWithDate:(NSDate *)date {
    
        NSCalendar * calendar = [NSCalendar currentCalendar];
    
        NSDateComponents *weekdayComponents = [calendar components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:date];
    
        NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:date];
        [components setDay:-((([weekdayComponents weekday] - [calendar firstWeekday]) + 5 ) % 7)];
    
        return [calendar dateFromComponents:components];
    }
    

    【讨论】:

    • 不错的扩展...如果当前日期已经是周开始日期,则此扩展不起作用。
    • 你不可能是正确的。如果日期是当月的第一天,则组件无效。
    【解决方案6】:

    如果星期一 (2) 设置为第一个工作日并且您正在检查的日期是星期日,则 naixn 的解决方案将产生错误的结果。在这种情况下,您将获得下周星期一的结果。

    正确的方法是按如下方式计算减法分量:

    [componentsToSubtract setDay: - ((([weekdayComponents weekday] - [gregorian firstWeekday])
                                      + 7 ) % 7)];
    

    假设您每周总是有 7 天。

    【讨论】:

      【解决方案7】:

      我认为此线程响应了您正在寻找的内容:http://www.cocoabuilder.com/archive/cocoa/211648-nsdatecomponents-question.html#211826

      但请注意,它不会将星期一作为一周的第一天处理,因此您可能需要通过减去 [gregorian firstWeekday] 而不仅仅是 1 来稍微调整一下。另外,我将其修改为使用-currentCalendar,但这取决于你:-)

      NSDate *today = [NSDate date];
      NSCalendar *gregorian = [NSCalendar currentCalendar];
      
      // Get the weekday component of the current date
      NSDateComponents *weekdayComponents = [gregorian components:NSWeekdayCalendarUnit fromDate:today];
      /*
      Create a date components to represent the number of days to subtract
      from the current date.
      The weekday value for Sunday in the Gregorian calendar is 1, so
      subtract 1 from the number
      of days to subtract from the date in question.  (If today's Sunday,
      subtract 0 days.)
      */
      NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init];
      /* Substract [gregorian firstWeekday] to handle first day of the week being something else than Sunday */
      [componentsToSubtract setDay: - ([weekdayComponents weekday] - [gregorian firstWeekday])];
      NSDate *beginningOfWeek = [gregorian dateByAddingComponents:componentsToSubtract toDate:today options:0];
      
      /*
      Optional step:
      beginningOfWeek now has the same hour, minute, and second as the
      original date (today).
      To normalize to midnight, extract the year, month, and day components
      and create a new date from those components.
      */
      NSDateComponents *components = [gregorian components: (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
                                                  fromDate: beginningOfWeek];
      beginningOfWeek = [gregorian dateFromComponents: components];
      

      【讨论】:

      • 请注意,您的日历命名可能有点误导。在大多数情况下,currentCalendar 将是公历,但没有为任何语言环境定义它。相反,我只想将指针命名为 calendar.
      • 正如@Wolfgang 所指出的,对于todayfirstWeekday 早于一周的情况(例如,firstWeekday=Monday 和 today=Sunday),此解决方案是不正确的。
      • @JasonMoore NSWeekdayCalendarUnitNSCalendarUnitWeekday 取代。他们只是让他们的命名方案更加一致(我在看着你,NSMakeRange)。您提到的更正是针对NSWeekCalendarUnit
      • 真的,@DanBlakemore!我已经删除了我的评论,因为你的评论涵盖了它。 (是的,我也讨厌倒退的NSMakeRange!)
      【解决方案8】:

      使用NSDateComponents 并将weekday 设置为1。

      【讨论】:

      • 那么dateComponents无效。
      猜你喜欢
      • 2012-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多