Calculate seconds between current time and next event

守給你的承諾、 提交于 2019-12-20 03:53:40

问题


This should be simple, but it's proving challenging for me. I'd like to know the best approach to calculating the difference in seconds between [NSDate date] and a future event x seconds from that time. There are several different types of event, and each event may occur several times a day, and at different times, depending what day of the week it happens to be.

What I am trying to do is have the user select an event type from a picker and then set an alarm in Notification Center for the next occurrence of that event based on their selection. I have everything working fine, except for the seconds calculation.

So, for example, let's say it's 9am on a Monday. I'd like to determine how many seconds it would be between now and a user selected event that regularly occurs every Tuesday, Thursday, and Saturday at 10am, 4pm, and 11pm on each day, or on Sunday at 1pm. How would you approach this most efficiently?


回答1:


When you're talking about a time or date like "next Thursday at 1 PM", that's information that only makes sense in the context of a calendar. NSDate is not going to provide you with much help. It would perhaps be more appropriately named NSPointInTime. It's just a number of seconds that have passed from some earlier, arbitrary reference point in time. It has no notion of weekdays, ante/post meridiem, or even hour of the day.

The two objects that do know about those sorts of thing are NSDateComponents and NSCalendar. Working together, they can create an NSDate from a specification like "next Thursday at 1PM".

You can decompose any date into components using -[NSCalendar components:fromDate:], and you can then use other NSDateComponents objects to perform arithmetic on the individual pieces of information. Find the weekday of today, for example, and its difference from Thursday. Then use -[NSCalendar dateByAddingComponents:toDate:options:] to create a new date based on that offset.

@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;
}


来源:https://stackoverflow.com/questions/17394338/calculate-seconds-between-current-time-and-next-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!