2011-01-18 12 views
5

Estoy tratando de hacer algo que, para mí, es un poco difícil. Pero estoy seguro de que alguien tiene alguna idea.NSDate - hace un año, dilema

Dada una fecha, digamos January 17, 2011, estoy tratando de averiguar el día que corresponde a esta fecha hace un año. Así que January 17, 2011 es un lunes, y hace un año, este día cayó en January 18, 2010 (un lunes también). Resulta que January 18, 2010 es 354 días antes de January 17, 2011. Originalmente pensé simplemente restar 365 días para un año no bisiesto y 366 días para un año bisiesto, pero si lo haces en este caso, obtendrás January 17, 2010, que es un domingo, no un lunes.

Así, en Objective-C con NSDate y NSCalendar, ¿cómo podría implementar una función, tales como:

-(NSDate *)logicalOneYearAgo:(NSDate *)from { 
} 

En otras palabras, el enésimo "día de la semana" del mes de orden n (donde "día de la semana" es Lunes, martes, miércoles, etc.)

+3

Vas a tener que definir mejor exactamente cuáles son sus expectativas; un año desde el 17 de enero de 2011 es el 17 de enero de 2010. ¿Desea (por ejemplo) el lunes n del mes n? –

+0

sí, el enésimo "día de la semana" del mes n. – CodeGuy

+0

Este mes tiene cinco lunes, mientras que enero de 2010 solo tuvo cuatro. ¿Cuál es la fecha un año antes del 31 de enero de 2011 en este esquema de fecha? – Chuck

Respuesta

-8

La respuesta resultó ser bastante simple. Resultó de prueba y error. Aquí está la respuesta.

si el año es bisiesto, reste 365 días.

si el año no es bisiesto, reste 364 días.

+0

luego acepte su propia respuesta. –

+3

¿Qué podría salir mal? – titaniumdecoy

+0

Esto ni siquiera hace lo que solicitó. Esta pregunta y su respuesta son un tren de guerra. –

3

No puedo garantizar que esta sea la forma más eficiente, pero puede hacerlo usando NSCalendar y NSDateComponents. Pase su instancia NSDate al [yourCalendar components:yourComponents fromDate:yourDate], reste un año de los componentes y luego use [yourCalendar dateFromComponents:yourComp].

Lo siento por no proporcionar el código completo, pero ha pasado un tiempo desde que trabajé con esos métodos, y no quiero darle un código que no funcione.

+0

esto también resulta en el problema que mencioné en la pregunta. Si "desde" es el 17 de enero de 2011, esta idea volverá el 17 de enero de 2010 (sin embargo, debo devolverla el 18 de enero de 2010). – CodeGuy

22

Se utilizan NSDateComponents así:

- (NSDate *)logicalOneYearAgo:(NSDate *)from { 

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

    NSDateComponents *offsetComponents = [[[NSDateComponents alloc] init] autorelease]; 
    [offsetComponents setYear:-1]; 

    return [gregorian dateByAddingComponents:offsetComponents toDate:from options:0]; 

} 
+0

esto da como resultado el problema que indiqué en la pregunta. Si "desde" es el 17 de enero de 2011, este método regresará el 17 de enero de 2010 (sin embargo, necesito que regrese el 18 de enero de 2010). – CodeGuy

0

Restar 1 año. Luego resta 1 día hasta que termines el mismo día de la semana que deseas.

Cada año los "días de la semana" se remontan 1 día, excepto cuando hay un 29 de febrero en el medio, se remontan 2 días.

Es porque un año es de 52 semanas + 1 día (+2 para años bisiestos).

Así que si aplica esta lógica indefinidamente, terminará, años después de años, teniendo un 16 de junio al 24 de mayo.

Si no desea que eso suceda, debe memorizar el año de referencia y basar su aritmética en algún lugar.

Por ejemplo, si el "nuevo" lunes es 4 días atrás (porque han pasado 3 años), puede preferir elegir el lunes 3 días adelante en el tiempo, para no restar días indefinidamente, años tras años.

Espero que ayude.

11

Esto se cubre en la sección Date and Time Programming Guide en cálculos de calendario, Adding Components to a Date

Específicamente, el método de interés es dateByAddingComponents:toDate:options.

Usando el ejemplo de Apple como base, para restar un año a partir de la fecha actual, debería hacer lo siguiente:

NSDate *today = [[NSDate alloc] init]; 
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 

/* 
    Create a date components to represent the number of years to add to the current date. 
    In this case, we add -1 to subtract one year.  
*/ 

NSDateComponents *addComponents = [[NSDateComponents alloc] init]; 
addComponents.year = - 1; 

return [calendar dateByAddingComponents:addComponents toDate:today options:0];