2008-10-08 27 views
12

¿Hay alguna forma mejor de hacerlo?¿Hay una mejor manera de encontrar la medianoche mañana?

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

Tenga en cuenta que siempre quiero la próxima medianoche, incluso si pasa a ser la medianoche cuando hago esa llamada, sin embargo, si resulta que es 23:59:59, que por supuesto quiero la medianoche que se avecina en un segundo

Las funciones de lenguaje natural parecen escamosas, y no estoy seguro de lo que Cacao haría si paso 32 en el campo "día". (Si eso trabajaría pude soltar los [ahora dateByAddingYears: ...] llamada)

Respuesta

25

Desde el documentation:

El uso de NSCalendarDate fuertemente desanime. Todavía no está en desuso, , sin embargo, puede estar en la próxima versión de OS después de Mac OS X v10.5. Para cálculos de calendario, usted debe utilizar combinaciones adecuadas de NSCalendar, NSDate y NSDateComponents, como se describe en calendarios en Dates and Times Programming Topics for Cocoa.

Siguiendo este consejo:

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

(No estoy seguro de improviso si esto es la implementación más eficiente, sino que debería servir como un puntero en la dirección correcta.)

Nota : En teoría, puede reducir la cantidad de código al permitir que los componentes de fecha presenten valores mayores que el rango de valores normales para el componente (por ejemplo, simplemente agregue 1 al componente del día, lo que puede dar como resultado un valor de 32) . Sin embargo, aunque dateFromComponents:puede tolerar valores fuera de límites, no está garantizado. Le recomendamos encarecidamente que no confíe en él.

+0

Y después de eso puntero, parece que puedo cortar la mayor parte de eso ya que dateFromComponents * does * parece tolerar días después del final del mes. – Dre

+0

dateFromComponents * puede * tolerar valores fuera de límites, pero no está garantizado. Le recomendamos encarecidamente que no confíe en eso. – mmalc

+0

Estoy en la costa este, y durante todo el día de hoy cuando realizo la conversión anterior, obtengo 1AM (mi tiempo de salida es de -5 horas, pero parece que NSCalendar está convencido de que son -4 horas. (Incluso si explícitamente configure la zona horaria) –

0

Convierta su fecha y hora actuales a una fecha Unix (segundos desde 1970) o estilo DOS (desde 1980), luego agregue 24 horas y conviértalo nuevamente. Luego restablezca las horas, los minutos y los segundos a cero para llegar a la medianoche.

+0

No funciona bien para algunas cajas de ahorro de luz diurna. – Andrew

7

No, será de la misma forma en que lo usa para encontrar la medianoche de hoy.

+0

awww c'mon. ¡eso fue divertido! – loudej

+1

Me temo que la gente aquí tiene detectores de ironía/humor muy defectuosos. Si no marca sus comentarios divertidos como tales, será votado negativamente. BTDT. – JesperE

+0

No rechazaré su respuesta, pero incluso suponiendo que fuera graciosa, ¿cuál es la broma? ¿Una breve respuesta frívola que ignora los detalles de la pregunta? Podrías usar tu "broma" para cada pregunta técnica en SO. POR ESO no es gracioso. –

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

Enfoque interesante (y lo superé por eso), pero tenga en cuenta la precaución en la documentación: "Puede dar resultados inesperados y se desaconseja su uso". –

+0

Gracias, estaba buscando una solución mejor también, ya que el SDK de iPhone no me gusta cuando lo uso, pero todavía funciona por ahora :) – 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

Cada vez que un programador define un día como 60 * 60 * 24, un segundo intercalar muere. No hagas esto – cbowns

0

Usted podría intentar de esta manera:

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 

También es fácil de recuperar el intervalo de segundos si es necesario para establecer una NSTimer:

double intervalToMidnight = midnight.timeIntervalSinceNow; 
Cuestiones relacionadas