2008-10-08 18 views
12

Y a-t-il une meilleure façon de faire cela?Y a-t-il une meilleure façon de trouver minuit demain?

-(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]]; 
} 

Notez que je veux toujours la prochaine minuit, même si elle se trouve être minuit quand je fais cet appel, si elle arrive à être 23:59:59, je veux bien sûr de minuit qui vient en une seconde. Les fonctions du langage naturel semblent squameuses, et je ne sais pas ce que Cocoa ferait si je passais 32 dans le champ "day". (Si ce travailleriez je pouvais laisser tomber les [maintenant dateByAddingYears: ...] appel)

Répondre

25

De l'documentation:

Utilisation de NSCalendarDate fortement découragé. Il n'est pas encore déprécié, mais il peut être dans la prochaine version majeure OS après Mac OS X 10.5. Pour calculs calendrical, vous devez utiliser des combinaisons appropriées de NSCalendar, NSDate et NSDateComponents, comme décrit dans calendriers dans Dates and Times Programming Topics for Cocoa.

Après ce conseil:

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]; 

(Je ne sais pas si cela est désinvolture la mise en œuvre la plus efficace, mais il devrait servir de pointeur dans la bonne direction.)

Remarque : En théorie, vous pouvez réduire la quantité de code en autorisant un composant de date avec des valeurs supérieures à la plage de valeurs normales du composant (par exemple en ajoutant simplement 1 au composant de jour, ce qui peut lui donner une valeur de 32) . Cependant, bien que dateFromComponents:puisse tolérer des valeurs hors limites, cela n'est pas garanti. Vous êtes fortement encouragé à ne pas compter dessus.

+0

Et suivant de cette pointeur, il semble que je puisse couper la plupart de ce que dateFromComponents * semble * tolérer des jours après la fin du mois. – Dre

+0

dateFromComponents * peut * tolérer des valeurs hors limites, mais cela n'est pas garanti. Vous êtes fortement encouragé à ne pas compter sur cela. – mmalc

+0

Je suis sur la côte est, et toute la journée aujourd'hui quand je fais la conversion ci-dessus, je reçois 1 heure (Mon temps est de -5 heures, mais il semble que NSCalendar est convaincu que c'est 4 heures. –

0

Convertissez votre date et heure actuelle en un format Unix (secondes depuis 1970) ou DOS (depuis 1980), puis ajoutez 24 heures et convertissez-le. Puis réinitialisez les heures, minutes et secondes à zéro pour arriver à minuit.

+0

Ne fonctionne pas correctement pour certains cas d'avantage d'heure d'été. – Andrew

7

Non, ce sera la même façon que vous utilisez pour trouver minuit aujourd'hui.

+0

awww c'mon. c'était amusant! – loudej

+1

J'ai peur que les gens ici aient des détecteurs d'ironie/d'humour très défectueux. Si vous ne marquez pas vos commentaires amusants en tant que tels, vous obtiendrez downvoted. BTDT. – JesperE

+0

Je ne vais pas baisser votre réponse, mais même en supposant que c'était drôle, quelle est la blague? Une réponse brève et désinvolte qui ignore les détails de la question? Vous pouvez utiliser votre "blague" pour chaque question technique sur SO. C'est pourquoi ce n'est pas drôle. –

1
[NSDate dateWithNaturalLanguageString:@"midnight tomorrow"]; 
+0

Approche intéressante (et j'ai upvoted pour cela), mais notez la prudence dans la documentation: "Cela peut donner des résultats inattendus, et son utilisation est fortement déconseillée." –

+0

Merci, je cherchais une meilleure solution aussi depuis l'iPhone sdk n'aime pas quand je l'utilise, mais ça marche encore pour le moment :) – user58338

4
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]; 
+6

Chaque fois qu'un programmeur définit un jour comme 60 * 60 * 24, une seconde intercalaire meurt. Ne fais pas ça. – cbowns

0

Vous pouvez essayer cette façon:

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 

Il est également facile de récupérer l'intervalle de secondes si nécessaire pour mettre en place un NSTimer:

double intervalToMidnight = midnight.timeIntervalSinceNow;