【问题标题】:NSDateComponents / NSDate : get the last sundayNSDateComponents / NSDate : 获取最后一个星期日
【发布时间】:2013-12-13 02:23:01
【问题描述】:

我知道有一些与此类似的问题,但我就是找不到我的代码有什么问题。

基本上我想要的是如果今天不是星期天, currentDate 设置为最后一个星期天。 如果今天是星期天,我将 currentDate 设置为之前的星期天。

这就是我的尝试。

  NSDateComponents *components = [[NSCalendar currentCalendar] components:  NSWeekCalendarUnit | NSYearCalendarUnit | NSWeekdayCalendarUnit fromDate:currentDate];

    if (components.weekday == 1) { //Its sunday. We just need to subtract a week
        [components setWeek: -1];
        currentDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:currentDate options:0];

    }else{ //If its not sunday we just go to sunday
        [components setWeekday: 1];
        currentDate = [[NSCalendar currentCalendar] dateFromComponents:components];

    }

第一次执行这部分代码时,我得到了正确的答案。在我第一次得到奇怪的日期之后,比如 4026 年 12 月 2 日,并且年份不断增加。

这是使它工作的代码:

   NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [calendar components: ( NSWeekCalendarUnit | NSWeekdayCalendarUnit | NSYearCalendarUnit) fromDate:currentDate];
    int weekday = components.weekday;

    if (weekday == 1) {
        [components setWeek:components.week -1];
    }else{
        [components setWeekday:1];
    }
    currentDate = [calendar dateFromComponents:components];

【问题讨论】:

  • 为什么将星期设置为-1?如果你想上周获得,只需components.week -= 1;
  • 我正在使用 dateByAddingComponents 并将日期设置为 -1 得到最后一天,我认为添加时将星期设置为 -1 得到最后一周。

标签: ios objective-c nsdate nscalendar nsdatecomponents


【解决方案1】:

如果您使用的是 iOS 8.0+,请使用 nextDateAfterDate.SearchBackwards 选项

let calendar = NSCalendar.currentCalendar()
let options: NSCalendarOptions = [.MatchPreviousTimePreservingSmallerUnits, .SearchBackwards]
calendar.nextDateAfterDate(NSDate(), matchingUnit: .Weekday, value: 1, options: options)

【讨论】:

  • @MatthewBahr 我不确定。 Swift 是现在 iOS 开发的首选语言。这个问题是在 2013 年 12 月,在 Swift 发布之前提出的。如果现在问这个问题,它很可能会被标记为 Swift。 iOS 开发者应该能够在 Obj-C 和 Swift 语法之间快速转换。
  • 仅仅因为它是“首选”语言并不意味着它很有帮助。我有 2 个 obj-c 库,仅出于维护原因,快速回答 obj c 问题并没有帮助。
  • @MatthewBahr 这在 SO 上很典型。如果您认为我的帖子不合适,我建议您标记我的帖子以供审核。最好的。
  • @MatthewBahr 不管首选语言是什么,问题的答案是使用 NSCalendar/Calendar 的哪个 API。并且在 ObjC 和 Swift 之间进行转换是相当容易的。
【解决方案2】:

在 NSCalendar 上试试这个类别

@interface NSCalendar (LastSunday)
-(NSDate *)previousSundayForDate:(NSDate *)date;
@end

@implementation NSCalendar (LastSunday)

-(NSDate *)previousSundayForDate:(NSDate *)date
{
    static NSUInteger SUNDAY = 1;
    static NSUInteger MONDAY = 2;

    NSDate *startOfWeek;
    [self rangeOfUnit:NSWeekCalendarUnit
            startDate:&startOfWeek
             interval:NULL
              forDate:date];

    if(self.firstWeekday == SUNDAY){

        NSDate *beginningOfDate;
        [self rangeOfUnit:NSDayCalendarUnit
                startDate:&beginningOfDate
                 interval:NULL forDate:date];
        if ([startOfWeek isEqualToDate:beginningOfDate]) {
            startOfWeek = [self dateByAddingComponents:(
                                                        {
                                                            NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                            comps.day = -7;
                                                            comps;
                                                        })
                                                toDate:startOfWeek
                                               options:0];
        }
        return startOfWeek;
    }
    if(self.firstWeekday == MONDAY)
        return [self dateByAddingComponents:(
                                             {
                                                 NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                 comps.day = -1;
                                                 comps;
                                             })
                                     toDate:startOfWeek
                                    options:0];

    return nil;

}

@end

将其用作:

NSDate *lastSunday = [calendar previousSundayForDate:[NSDate date]];

PS:

“一个方法一个返回声明”的版本-恋物癖:

@implementation NSCalendar (LastSunday)

-(NSDate *)previousSundayForDate:(NSDate *)date
{
    NSDate *resultDate = nil;
    static NSUInteger SUNDAY = 1;
    static NSUInteger MONDAY = 2;

    NSDate *startOfWeek;
    [self rangeOfUnit:NSWeekCalendarUnit
            startDate:&startOfWeek
             interval:NULL
              forDate:date];

    if(self.firstWeekday == SUNDAY){

        NSDate *beginningOfDate;
        [self rangeOfUnit:NSDayCalendarUnit
                startDate:&beginningOfDate
                 interval:NULL forDate:date];

        if ([startOfWeek isEqualToDate:beginningOfDate]) {
            startOfWeek = [self dateByAddingComponents:(
                                                        {
                                                            NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                            comps.day = -7;
                                                            comps;
                                                        })
                                                toDate:startOfWeek
                                               options:0];
        }
        resultDate = startOfWeek;
    }
    if(self.firstWeekday == MONDAY)
        resultDate = [self dateByAddingComponents:(
                                                   {
                                                       NSDateComponents *comps = [[NSDateComponents alloc] init];
                                                       comps.day = -1;
                                                       comps;
                                                   })
                                           toDate:startOfWeek
                                          options:0];

    return resultDate;

}

@end

【讨论】:

  • 效果很好,但是当我使用此代码时,返回的日期怎么会设置为凌晨 5 点?
  • 这已被讨论了数千次。但基本上 nsdates 实例在打印时显示 gmt 时间。
【解决方案3】:

你得到 4026 的原因是因为这行:

NSDateComponents *components = [[NSCalendar currentCalendar] components:  NSWeekCalendarUnit | NSYearCalendarUnit | NSWeekdayCalendarUnit fromDate:currentDate];

它将年份组件设置为当前年份,2013 年。它还初始化周和工作日组件。然后将组件添加到当前日期,将年份翻倍至 4026,此处:

[components setWeek: -1];
currentDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:currentDate options:0];

如果您只想减去一周,请这样做:

NSDateComponents *components = [[NSDateComponents alloc] init];
[components setWeek: -1];
currentDate = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:currentDate options:0];
[components release];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多