iphone - pasar - reducir segundos a horas
Cómo convertir un NSTimeInterval(segundos) en minutos (12)
¡Todos estos se ven más complicados de lo que deben ser! Aquí hay una manera breve y dulce de convertir un intervalo de tiempo en horas, minutos y segundos:
NSTimeInterval timeInterval = 326.4;
long seconds = lroundf(timeInterval); // Since modulo operator (%) below needs int or long
int hour = seconds / 3600;
int mins = (seconds % 3600) / 60;
int secs = seconds % 60;
Tenga en cuenta que cuando coloca un flotador en un int, obtiene floor () automáticamente, pero puede agregarlo a los dos primeros si lo hace sentir mejor :-)
Tengo una cantidad de segundos que pasó desde un cierto evento. Se almacena en un tipo de datos NSTimeInterval.
Quiero convertirlo en minutos y segundos.
Por ejemplo, tengo: "326.4 segundos" y quiero convertirlo en la siguiente cadena: "5:26".
¿Cuál es la mejor manera de lograr este objetivo?
Gracias.
Aquí hay una versión de Swift:
func durationsBySecond(seconds s: Int) -> (days:Int,hours:Int,minutes:Int,seconds:Int) {
return (s / (24 * 3600),(s % (24 * 3600)) / 3600, s % 3600 / 60, s % 60)
}
Se puede usar así:
let (d,h,m,s) = durationsBySecond(seconds: duration)
println("time left: /(d) days /(h) hours /(m) minutes /(s) seconds")
Cómo lo hice en Swift (incluido el formato de cadena para mostrarlo como "01:23"):
let totalSeconds: Double = someTimeInterval
let minutes = Int(floor(totalSeconds / 60))
let seconds = Int(round(totalSeconds % 60))
let timeString = String(format: "%02d:%02d", minutes, seconds)
NSLog(timeString)
Dado que es esencialmente un doble ...
Divide por 60.0 y extrae la parte integral y la parte fraccionaria.
La parte integral será la cantidad total de minutos.
Multiplique la parte fraccional por 60.0 nuevamente.
El resultado serán los segundos restantes.
El código de Brian Ramsay, de-pseudofied:
- (NSString*)formattedStringForDuration:(NSTimeInterval)duration
{
NSInteger minutes = floor(duration/60);
NSInteger seconds = round(duration - minutes * 60);
return [NSString stringWithFormat:@"%d:%02d", minutes, seconds];
}
Perdóname por ser una virgen de Stack ... No estoy seguro de cómo responder a la respuesta de Brian Ramsay ...
Usar la ronda no funcionará para los segundos valores entre 59.5 y 59.99999. El segundo valor será 60 durante este período. Use trunc en su lugar ...
double progress;
int minutes = floor(progress/60);
int seconds = trunc(progress - minutes * 60);
Si su objetivo es iOS 8 o OS X 10.10, es mucho más fácil. La nueva clase NSDateComponentsFormatter
permite convertir un NSTimeInterval
dado de su valor en segundos a una cadena localizada para mostrar al usuario. Por ejemplo:
C objetivo
NSTimeInterval interval = 326.4;
NSDateComponentsFormatter *componentFormatter = [[NSDateComponentsFormatter alloc] init];
componentFormatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional;
componentFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDropAll;
NSString *formattedString = [componentFormatter stringFromTimeInterval:interval];
NSLog(@"%@",formattedString); // 5:26
Rápido
let interval = 326.4
let componentFormatter = NSDateComponentsFormatter()
componentFormatter.unitsStyle = .Positional
componentFormatter.zeroFormattingBehavior = .DropAll
if let formattedString = componentFormatter.stringFromTimeInterval(interval) {
print(formattedString) // 5:26
}
NSDateCompnentsFormatter
también permite que esta salida esté en formularios más largos. Se puede encontrar más información en el artículo NSFormatter de NSHipster . Y dependiendo de las clases con las que ya esté trabajando (si no es NSTimeInterval
), puede ser más conveniente pasarle al formateador una instancia de NSDateComponents
, o dos objetos NSDate
, lo que también se puede hacer a través de los siguientes métodos.
C objetivo
NSString *formattedString = [componentFormatter stringFromDate:<#(NSDate *)#> toDate:<#(NSDate *)#>];
NSString *formattedString = [componentFormatter stringFromDateComponents:<#(NSDateComponents *)#>];
Rápido
if let formattedString = componentFormatter.stringFromDate(<#T##startDate: NSDate##NSDate#>, toDate: <#T##NSDate#>) {
// ...
}
if let formattedString = componentFormatter.stringFromDateComponents(<#T##components: NSDateComponents##NSDateComponents#>) {
// ...
}
Swift 2 versión
extension NSTimeInterval {
func toMM_SS() -> String {
let interval = self
let componentFormatter = NSDateComponentsFormatter()
componentFormatter.unitsStyle = .Positional
componentFormatter.zeroFormattingBehavior = .Pad
componentFormatter.allowedUnits = [.Minute, .Second]
return componentFormatter.stringFromTimeInterval(interval) ?? ""
}
}
let duration = 326.4.toMM_SS()
print(duration) //"5:26"
pseudo-código:
minutes = floor(326.4/60)
seconds = round(326.4 - minutes * 60)
Recuerde que la pregunta original es sobre un resultado de cadena, no un pseudocódigo o componentes de cadena individuales.
Quiero convertirlo en la siguiente cadena: "5:26"
A muchas respuestas les faltan los problemas de internacionalización, y la mayoría hace los cálculos matemáticos a mano. Todo tan del siglo XX ...
No hagas las matemáticas tú mismo (Swift 4)
let timeInterval: TimeInterval = 326.4
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.unitsStyle = .positional
if let formatted = dateComponentsFormatter.string(from: timeInterval) {
print(formatted)
}
5:26
Aproveche las bibliotecas
Si realmente desea componentes individuales y un código gratamente legible, consulte SwiftDate :
import SwiftDate
...
if let minutes = Int(timeInterval).seconds.in(.minute) {
print("/(minutes)")
}
5
Créditos a @mickmaccallum y @polarwar para un uso adecuado de DateComponentsFormatter
Breve descripción
- La respuesta de Brian Ramsay es más conveniente si solo desea convertir a minutos.
- Si desea que Cocoa API lo haga por usted y convierta su NSTimeInterval no solo en minutos, sino también en días, meses, semanas, etc. ... Creo que este es un enfoque más genérico.
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 el NSTimeInterval que deseas convertir. (Si su NSTimeInterval proviene de comparar 2 NSDate, no necesita hacer este paso, y ni siquiera necesita el NSTimeInterval).
Obtenga sus presupuestos de NSDateComponents
Código de muestra
// The time interval
NSTimeInterval theTimeInterval = 326.4;
// 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
unsigned int unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit;
NSDateComponents *conversionInfo = [sysCalendar components:unitFlags fromDate:date1 toDate:date2 options:0];
NSLog(@"Conversion: %dmin %dhours %ddays %dmoths",[conversionInfo minute], [conversionInfo hour], [conversionInfo day], [conversionInfo month]);
[date1 release];
[date2 release];
Problemas conocidos
- Demasiado para una conversión, tienes razón, pero así es como funciona la API.
- Mi sugerencia: si te acostumbras a administrar tus datos de tiempo usando NSDate y NSCalendar, la API hará el trabajo por ti.
NSDate *timeLater = [NSDate dateWithTimeIntervalSinceNow:60*90];
NSTimeInterval duration = [timeLater timeIntervalSinceNow];
NSInteger hours = floor(duration/(60*60));
NSInteger minutes = floor((duration/60) - hours * 60);
NSInteger seconds = floor(duration - (minutes * 60) - (hours * 60 * 60));
NSLog(@"timeLater: %@", [dateFormatter stringFromDate:timeLater]);
NSLog(@"time left: %d hours %d minutes %d seconds", hours,minutes,seconds);
Productos:
timeLater: 22:27
timeLeft: 1 hours 29 minutes 59 seconds