计算当前时间和下一个事件之间的秒数

时间:2013-06-30 20:02:55

标签: cocoa cocoa-touch nsdate nscalendar date-arithmetic

这应该很简单,但对我来说这是一个挑战。我想知道计算[NSDate date]与未来事件x秒之间的差异的最佳方法。有几种不同类型的事件,每个事件可能每天发生几次,并且在不同的时间,取决于它恰好是一周的哪一天。

我要做的是让用户从选择器中选择一个事件类型,然后在Notification Center中根据他们的选择在下一次出现该事件时设置一个警报。我有一切正常,除了秒计算。

所以,例如,假设是星期一早上9点。我想确定从现在到每周二,周四和周六上午10点,下午4点和晚上11点或周日下午1点经常发生的用户选择事件之间的秒数。您如何最有效地解决这个问题?

1 个答案:

答案 0 :(得分:1)

当你谈论像“下周四下午1点”这样的时间或日期时,这些信息只在日历的背景下才有意义。 NSDate不会为您提供太多帮助。它可能更恰当地命名为NSPointInTime。从一些早期的任意参考时间点开始,它只是几秒钟。它没有工作日,前/后经济,甚至一小时的概念。

知道这些事情的两个对象是NSDateComponentsNSCalendar。通过合作,他们可以从“下周四下午1点”等规范中创建NSDate

您可以使用-[NSCalendar components:fromDate:]将任何日期分解为组件,然后您可以使用其他NSDateComponents对象对各条信息执行算术运算。例如,查找今天的工作日,以及它与周四的差异。然后使用-[NSCalendar dateByAddingComponents:toDate:options:]根据该偏移量创建新日期。

@interface NSCalendar (NextWeekday)

- (NSInteger)maxWeekday;

- (NSDate *)dateFromComponents:(NSDateComponents *)comps
                forNextWeekday:(NSInteger)weekday
                        atHour:(NSInteger)hour;

@end

@implementation NSCalendar (NextWeekday)

- (NSInteger)maxWeekday
{
    return [self maximumRangeOfUnit:NSWeekdayCalendarUnit].length;
}

- (NSDate *)dateFromComponents:(NSDateComponents *)comps
                forNextWeekday:(NSInteger)weekday
                        atHour:(NSInteger)hour
{
    NSInteger diff = weekday - [comps weekday];
    if( diff < 0 ){
        diff += [self maxWeekday];
    }

    NSDateComponents * weekdayOffset = [NSDateComponents new];
    [weekdayOffset setWeekday:diff];

    [comps setHour:hour];

    return [self dateByAddingComponents:weekdayOffset
                                 toDate:[self dateFromComponents:comps]
                                options:0];
}


@end

#define GREGORIAN_THURSDAY 5

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        NSCalendar * cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

        NSDateComponents * wednesday = [NSDateComponents new];
        [wednesday setDay:3];
        [wednesday setWeekday:4];
        [wednesday setMonth:6];
        [wednesday setYear:2013];

        NSDateComponents * friday = [NSDateComponents new];
        [friday setDay:5];
        [friday setWeekday:6];
        [friday setMonth:6];
        [friday setYear:2013];

        NSDateComponents * now = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSWeekdayCalendarUnit
                                        fromDate:[NSDate date]];


        NSDateComponents * lastSatOfDecember = [NSDateComponents new];
        [lastSatOfDecember setDay:29];
        [lastSatOfDecember setWeekday:7];
        [lastSatOfDecember setMonth:12];
        [lastSatOfDecember setYear:2012];

        NSLog(@"From Wednesday: %@", [cal dateFromComponents:wednesday
                                              forNextWeekday:GREGORIAN_THURSDAY
                                                      atHour:13]);
        NSLog(@"From Friday: %@", [cal dateFromComponents:friday
                                           forNextWeekday:GREGORIAN_THURSDAY
                                                   atHour:13]);
        NSLog(@"From now: %@", [cal dateFromComponents:now
                                        forNextWeekday:GREGORIAN_THURSDAY
                                                atHour:13]);
        NSLog(@"Crossing over the year: %@", [cal dateFromComponents:lastSatOfDecember
                                                     forNextWeekday:GREGORIAN_THURSDAY
                                                             atHour:13]);

    }
    return 0;
}