问题
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