¿Cómo se descompone un NSTimeInterval en año, meses, días, horas, minutos y segundos en el iPhone?
cocoa (9)
Aquí hay otra posibilidad, algo más limpia:
NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSString *dateStr = [date description];
const char *dateStrPtr = [dateStr UTF8String];
// format: YYYY-MM-DD HH:MM:SS ±HHMM
int year, month, day, hour, minutes, seconds;
sscanf(dateStrPtr, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minutes, &seconds);
year -= 1970;
Tengo un intervalo de tiempo que abarca años y quiero componentes todo el tiempo del año a segundos.
Mi primer pensamiento es dividir en números enteros el intervalo de tiempo por segundos en un año, restarlo de un total acumulado de segundos, dividirlo por segundos en un mes, restarlo del total acumulado, y así sucesivamente.
Eso parece enrevesado y he leído que cada vez que haces algo que parece intrincado, probablemente haya un método incorporado.
¿Esta ahí?
Integré el segundo método de Alex en mi código.
Está en un método llamado por un UIDatePicker en mi interfaz.
NSDate *now = [NSDate date];
NSDate *then = self.datePicker.date;
NSTimeInterval howLong = [now timeIntervalSinceDate:then];
NSDate *date = [NSDate dateWithTimeIntervalSince1970:howLong];
NSString *dateStr = [date description];
const char *dateStrPtr = [dateStr UTF8String];
int year, month, day, hour, minute, sec;
sscanf(dateStrPtr, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &sec);
year -= 1970;
NSLog(@"%d years/n%d months/n%d days/n%d hours/n%d minutes/n%d seconds", year, month, day, hour, minute, sec);
Cuando configuro el selector de fechas en 1 fecha y 1 día en el pasado, obtengo:
1 año 1 mes 1 día 16 horas 0 minutos 20 segundos
que es de 1 mes y 16 horas de descanso. Si configuré el selector de fecha en 1 día en el pasado, estoy fuera de la misma cantidad.
Actualización : tengo una aplicación que calcula su edad en años, dado su cumpleaños (configurado a partir de un UIDatePicker), pero a menudo estaba apagado. Esto prueba que hubo una inexactitud, pero no puedo entender de dónde viene, ¿verdad?
Convierta su intervalo en un NSDate
usando +dateWithIntervalSince1970
, obtenga los componentes de la fecha usando el método -componentsFromDate
.
Desde iOS8 y superior puedes usar NSDateComponentsFormatter
Tiene métodos para convertir la diferencia de tiempo en una cadena formateada fácil de usar.
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull;
NSLog(@"%@", [formatter stringFromTimeInterval:1623452]);
Esto da la salida - 2 semanas, 4 días, 18 horas, 57 minutos, 32 segundos
Este código es consciente de los tiempos de ahorro de luz diurna y otras posibles cosas desagradables.
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorianCalendar components: (NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit )
fromDate:startDate
toDate:[NSDate date]
options:0];
NSLog(@"%ld", [components year]);
NSLog(@"%ld", [components month]);
NSLog(@"%ld", [components day]);
NSLog(@"%ld", [components hour]);
NSLog(@"%ld", [components minute]);
NSLog(@"%ld", [components second]);
Esto funciona para mí:
float *lenghInSeconds = 2345.234513;
NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:lenghInSeconds];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
[formatter setDateFormat:@"HH:mm:ss"];
NSLog(@"%@", [formatter stringFromDate:date]);
[formatter release];
La principal diferencia aquí es que debe ajustar para la zona horaria.
O está mi método de clase. No maneja años, pero podría agregarse fácilmente, aunque es mejor para pequeños tiempos como días, horas y minutos. Toma los plurales en cuenta y solo muestra lo que se necesita:
+(NSString *)TimeRemainingUntilDate:(NSDate *)date {
NSTimeInterval interval = [date timeIntervalSinceNow];
NSString * timeRemaining = nil;
if (interval > 0) {
div_t d = div(interval, 86400);
int day = d.quot;
div_t h = div(d.rem, 3600);
int hour = h.quot;
div_t m = div(h.rem, 60);
int min = m.quot;
NSString * nbday = nil;
if(day > 1)
nbday = @"days";
else if(day == 1)
nbday = @"day";
else
nbday = @"";
NSString * nbhour = nil;
if(hour > 1)
nbhour = @"hours";
else if (hour == 1)
nbhour = @"hour";
else
nbhour = @"";
NSString * nbmin = nil;
if(min > 1)
nbmin = @"mins";
else
nbmin = @"min";
timeRemaining = [NSString stringWithFormat:@"%@%@ %@%@ %@%@",day ? [NSNumber numberWithInt:day] : @"",nbday,hour ? [NSNumber numberWithInt:hour] : @"",nbhour,min ? [NSNumber numberWithInt:min] : @"00",nbmin];
}
else
timeRemaining = @"Over";
return timeRemaining;
}
Breve descripción
Solo otro enfoque para completar la respuesta de JBRWilkinson pero agregando algún código. También puede ofrecer una solución al comentario de Alex Reynolds.
Use el método NSCalendar:
(NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSUInteger)opts
"Devuelve, como un objeto NSDateComponents utilizando componentes especificados, la diferencia entre dos fechas proporcionadas". (De la documentación API).
Crea 2 NSDate cuya diferencia es NSTimeInterval que quieres desglosar. (Si su NSTimeInterval proviene de comparar 2 NSDate, no necesita hacer este paso, y ni siquiera necesita NSTimeInterval, solo aplique las fechas al método NSCalendar).
Obtenga sus presupuestos de NSDateComponents
Código de muestra
// The time interval
NSTimeInterval theTimeInterval = ...;
// Get the system calendar
NSCalendar *sysCalendar = [NSCalendar currentCalendar];
// Create the NSDates
NSDate *date1 = [[NSDate alloc] init];
NSDate *date2 = [[NSDate alloc] initWithTimeInterval:theTimeInterval sinceDate:date1];
// Get conversion to months, days, hours, minutes
NSCalendarUnit unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit;
NSDateComponents *breakdownInfo = [sysCalendar components:unitFlags fromDate:date1 toDate:date2 options:0];
NSLog(@"Break down: %i min : %i hours : %i days : %i months", [breakdownInfo minute], [breakdownInfo hour], [breakdownInfo day], [breakdownInfo month]);
- (NSString *)convertTimeFromSeconds:(NSString *)seconds {
// Return variable.
NSString *result = @"";
// Int variables for calculation.
int secs = [seconds intValue];
int tempHour = 0;
int tempMinute = 0;
int tempSecond = 0;
NSString *hour = @"";
NSString *minute = @"";
NSString *second = @"";
// Convert the seconds to hours, minutes and seconds.
tempHour = secs / 3600;
tempMinute = secs / 60 - tempHour * 60;
tempSecond = secs - (tempHour * 3600 + tempMinute * 60);
hour = [[NSNumber numberWithInt:tempHour] stringValue];
minute = [[NSNumber numberWithInt:tempMinute] stringValue];
second = [[NSNumber numberWithInt:tempSecond] stringValue];
// Make time look like 00:00:00 and not 0:0:0
if (tempHour < 10) {
hour = [@"0" stringByAppendingString:hour];
}
if (tempMinute < 10) {
minute = [@"0" stringByAppendingString:minute];
}
if (tempSecond < 10) {
second = [@"0" stringByAppendingString:second];
}
if (tempHour == 0) {
NSLog(@"Result of Time Conversion: %@:%@", minute, second);
result = [NSString stringWithFormat:@"%@:%@", minute, second];
} else {
NSLog(@"Result of Time Conversion: %@:%@:%@", hour, minute, second);
result = [NSString stringWithFormat:@"%@:%@:%@",hour, minute, second];
}
return result;
}
NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
// format: YYYY-MM-DD HH:MM:SS ±HHMM
NSString *dateStr = [date description];
NSRange range;
// year
range.location = 0;
range.length = 4;
NSString *yearStr = [dateStr substringWithRange:range];
int year = [yearStr intValue] - 1970;
// month
range.location = 5;
range.length = 2;
NSString *monthStr = [dateStr substringWithRange:range];
int month = [monthStr intValue];
// day, etc.
...