Есть лучший способ найти полночь завтра?

Есть ли лучший способ сделать это?

-(NSDate *)getMidnightTommorow {
    NSCalendarDate *now = [NSCalendarDate date];
    NSCalendarDate *tomorrow = [now dateByAddingYears:0 months:0 days:1 hours:0 minutes:0 seconds:0];
    return [NSCalendarDate dateWithYear:[tomorrow yearOfCommonEra]
                                  month:[tomorrow monthOfYear]
                                    day:[tomorrow dayOfMonth]
                                   hour:0
                                 minute:0
                                 second:0
                               timeZone:[tomorrow timeZone]];
}

Заметьте, что я всегда хочу следующей полуночи, даже если это будет полночь, когда я делаю этот звонок, однако, если это произойдет 23:59:59, я, конечно, хочу, чтобы полуночи пришли в одну секунду.

Функции естественного языка кажутся шелушащимися, и я не уверен, что будет делать Cocoa, если я пройду 32 в поле "день". (Если бы это сработало, я мог бы сбросить вызов [now dateByAddingYears:...])

Ответы

Ответ 1

Из documentation:

Использование NSCalendarDate сильно не рекомендуется. Он еще не устарел, однако это может быть в следующей крупной ОС релиз после Mac OS X v10.5. Для календарных расчетов, вы должны используйте подходящие комбинации NSCalendar, NSDate и NSDateComponents, как описано в Календари в Даты и время Темы программирования для Cocoa.

Следуя этому совету:

NSDate *today = [NSDate date];

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

NSDateComponents *components = [[NSDateComponents alloc] init];
components.day = 1;
NSDate *tomorrow = [gregorian dateByAddingComponents:components toDate:today options:0];
[components release];

NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit;
components = [gregorian components:unitFlags fromDate:tomorrow];
components.hour = 0;
components.minute = 0;

NSDate *tomorrowMidnight = [gregorian dateFromComponents:components];

[gregorian release];
[components release];

(Я не уверен, если это наиболее эффективная реализация, но она должна служить указателем в правильном направлении.)

Примечание. В теории вы можете уменьшить количество кода здесь, разрешив объект компонентов даты со значениями, превышающими диапазон нормальных значений для компонента (например, просто добавив 1 к компоненту дня, что может привести к тому, что он будет иметь значение 32). Однако, хотя dateFromComponents: может переносить значения вне пределов, это не гарантируется. Вам настоятельно рекомендуется не полагаться на него.

Ответ 2

Нет - это будет так же, как вы сегодня используете полночь.

Ответ 3

NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];

NSDate *tomorrow = [NSDate dateWithTimeIntervalSinceNow:(24 * 60 * 60)];

NSDateComponents *components = [gregorian components:(NSYearCalendarUnit |
                                                      NSMonthCalendarUnit |
                                                      NSDayCalendarUnit)
                                            fromDate:tomorrow];

NSDate *midnight = [gregorian dateFromComponents:components];

Ответ 4

[NSDate dateWithNaturalLanguageString:@"midnight tomorrow"];

Ответ 5

Преобразуйте текущую дату и время в дату Unix (секунды с 1970 года) или стиль DOS (с 1980 года), затем добавьте 24 часа и преобразуйте их обратно. Затем reset часы, минуты и секунды до нуля, чтобы добраться до полуночи.

Ответ 6

Вы можете попробовать таким образом:

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:1];
NSDate *tomorrow = [calendar dateByAddingComponents:comps toDate:[NSDate date] options:0]; //it gives us tomorrow with current time
NSDate *midnight = [calendar startOfDayForDate:tomorrow]; //here we get next midnight

Также легко получить интервал секунд, если необходимо, чтобы настроить NSTimer:

double intervalToMidnight = midnight.timeIntervalSinceNow;