【问题标题】:Calculate seconds between current time and next event计算当前时间和下一个事件之间的秒数
【发布时间】:2013-06-30 20:02:54
【问题描述】:

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

我想做的是让用户从选择器中选择一个事件类型,然后根据他们的选择在通知中心为该事件的下一次发生设置警报。除了秒计算外,我一切正常。

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

【问题讨论】:

  • 最有效?因此,您编写了一些确实有效但效率极低的代码,以至于占用了您 iPhone 的所有 RAM 和 CPU,现在您正在寻找更高效的方法吗?
  • 没有显示一行代码的讨论有什么意义?还是只是另一个“给我代码”?
  • 不,我想知道最好的方法是什么。我可以写很多复杂的条件逻辑,然后把它放在一个循环中迭代询问'下一次发生的事件现在发生了吗?基于此的时间并从该结果中减去当前时间。然而,这似乎过于笨拙,我正在寻找更优雅的解决方案。
  • @RayRichards 你可以,但你为什么要打电话给[aDate timeIntervalSinceDate:anotherDate]
  • 谢谢 H2CO3,我想我的问题是我事先不知道 anotherDate 会是什么,只是事件有规律地发生,每天多次,时间不同,具体取决于日期一周中的。所以我想我的困难在于确定该变量的值。我想我只是有一个心理障碍!

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


【解决方案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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 2015-05-25
    相关资源
    最近更新 更多