【问题标题】:How can I get an NSDate for the first day of the next week of the month如何获得本月下一周第一天的 NSDate
【发布时间】:2012-12-12 14:20:14
【问题描述】:

给定一个任意日期,我需要找到该月下一周第一天的日期。请注意,它并不像在当前日期上增加 7 天那么简单,因为该月的最后一周可能少于 7 天。这是我现在使用的代码:

    NSCalendar* calendar = [NSCalendar currentCalendar];
    NSDateComponents* components = [calendar components:NSWeekOfMonthCalendarUnit|NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSDayCalendarUnit fromDate:currentDate];

    NSLog(@"week of month: %ld", [components weekOfMonth]);

    [components setWeekOfMonth:[components weekOfMonth] + 1];
    NSLog(@"new week of month: %ld", [components weekOfMonth]); //week of month is now 2

    [components setWeekday:1];
    NSDate *nextWeek = [calendar dateFromComponents:components];

例如,currentDate 设置为 2012-10-01。在此示例中,nextWeek 始终为 2012-10-01。似乎发送setWeekOfMonth: 不会增加NSDateComponents 对象中的其他日期组件。是我配置了错误的日期组件,还是 setWeekOfMonth: 不应该那样工作?

【问题讨论】:

  • 假设您的一周从星期一开始,今天是 12 月 27 日,那么您希望 12 月 31 日作为您的答案吗?
  • 是的,没错,假设 currentCalenar 设置为使用星期一作为一周的第一天。如果将星期日设置为一周的第一天,则 nextWeek 将是 12 月 30 日。
  • @MikeT :我已经发布了另一个答案,请告诉我,这是否再次正确?

标签: cocoa nsdate nscalendar nsdatecomponents


【解决方案1】:

所以....让我们从NSDateNSCalendar 开始:

NSDate *date = ...;
NSCalendar *cal = [NSCalendar currentCalendar];

找出该日期是星期几:

NSInteger weekdayOfDate = [cal ordinalityOfUnit:NSWeekdayCalendarUnit inUnit:NSWeekCalendarUnit forDate:date];
NSInteger numberOfDaysToStartOfCurrentWeek = weekdayOfDate - 1;

让我们把日期移到下周:

NSDateComponents *oneWeek = [[NSDateComponents alloc] init];
[oneWeek setWeek:1]; // add one week
[oneWeek setDay:-numberOfDaysToStartOfCurrentWeek]; // ... and subtract a couple of days to get the first day of the week
NSDate *startOfNextWeek = [cal dateByAddingComponents:oneWeek toDate:date options:0];

此时,您的日期指向下周的第一天。现在我们应该验证它仍然在同一个月份:

NSDateComponents *monthOfNextWeek = [cal components:NSMonthCalendarUnit fromDate:startOfNextWeek];
NSDateComponents *monthOfThisWeek = [cal components:NSMonthCalendarUnit fromDate:date];
if ([monthOfNextWeek month] != [monthOfThisWeek month]) {
  // the first day of the next week is not in the same month as the start date
}

当我运行这个时,我知道下周的开始时间是 2012 年 12 月 30 日(星期日,因为我的日历周从星期日开始)。

但是,如果我希望一周的第一天从星期一开始,我可以在这段代码前加上:

[cal setFirstWeekday:2]; // the first day of the week is the second day (ie, Monday, because Sunday = 1)

如果我这样做,那么 startOfNextWeek 的结果是 2012 年 12 月 31 日。

【讨论】:

  • 您能解释一下为什么要从 weekdayOfDate 中减去 1 吗?我不明白这如何让你知道到本周开始的天数。其余的我会遵循,我会尽快实现它,看看它是如何工作的。
  • @MikeT 基本上,因为工作日是从 1 开始的,而不是从 0 开始的。代码的作用是一步完成两个计算:首先添加一周,然后减去足够的天数以到达下一周的开始。 NSDateComponents 方便我们一步完成。
  • 所以如果date 对应于星期日(工作日1),那么numberOfDaysToStartOfCurrentWeek1 - 1,或者0(因为它已经是当前一周的开始)。因此,然后加上一周并减去 0 天,即可到达下一周的开始。
  • 这个工作除了我使用 [oneWeek setDay: [oneWeek day] - numberOfDaysToStartOfCurrentWeek];所以那一天永远不会被设置为 0
  • @MikeT 将其设置为 0 就可以了。但是,如果您不想将其设置为 0,则应该这样做 if (numberOfDaysToStartOfCurrentWeek > 0) { ... }
【解决方案2】:

这是一个有效的答案吗:

NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setLocale:[[NSLocale alloc]initWithLocaleIdentifier:@"en_US_POSIX"]];
[dateFormatter setDateFormat:@"EEE"];

NSDate *date=[NSDate date];
NSString *dateString=[dateFormatter stringFromDate:date];

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents *components = [NSDateComponents new];

[calendar setFirstWeekday:1];//1 for Mon

NSDate *newDate=date;

while (![dateString isEqualToString:@"Mon"]) {
    components.day = 1;
    newDate = [calendar dateByAddingComponents:components toDate:newDate options:0];
    dateString=[dateFormatter stringFromDate:newDate];
}
NSLog(@"Upcoming week Date=%@",newDate);

【讨论】:

  • 如果你走这条路线,你还必须将 dateFormatter 的语言环境设置为en_US_POSIX,因为这段代码会根据系统的语言环境而中断。 (例如,如果这是在讲西班牙语的系统上运行的,@"EEE" 将呈现为 @"Lun",而不是 @"Mon"
  • @DaveDeLong:天啊...我真的很高兴从 SO 和你那里学到很多东西。谢谢先生。我会更新答案。
猜你喜欢
  • 1970-01-01
  • 2011-03-20
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 2010-12-25
  • 1970-01-01
  • 2012-07-10
  • 1970-01-01
相关资源
最近更新 更多