如何将NSTimeInterval(秒)转换为分钟


104

seconds从某个事件中得到了很多。它存储在NSTimeInterval数据类型中。

我想将其转换为minutesseconds

例如,我有:“ 326.4”秒,我想将其转换为以下字符串:“ 5:26”。

实现这个目标的最佳方法是什么?

谢谢。

Answers:


147

伪代码:

minutes = floor(326.4/60)
seconds = round(326.4 - minutes * 60)

90
我认为值得一提的是NSTimerInterval只是double的typedef。
Armentage 2010年

4
请参见Albaregar的答案-这是一种更好的方法(代码更多,但更灵活,可维护)
benvolioT 2010年

1
但是,该代码非常昂贵。对于以秒为单位的持续时间的快速转换,此答案更好。
SpacyRicochet 2012年

2
请注意,此答案将为您提供1:60的内容。看一下更接近事实的StratFan的答案。但是移开地面和地面,您应该有空的家。
InvulgoSoft 2012年

在撰写此评论时,Mick MacCallum在下面的回答似乎是最新的,并且是通过使用本机API做出的。
Tomasz Nazarenko

183

简要描述;简介

  1. 如果您只想转换为分钟,Brian Ramsay的答案将更为方便。
  2. 如果您想让Cocoa API做到这一点,并将NSTimeInterval不仅转换为分钟,还转换为几天,几个月,一周等,...我认为这是一种更通用的方法
  3. 使用NSCalendar方法:

    • (NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSUInteger)opts

    • “使用指定的组件作为两个NSDateComponents对象返回两个提供的日期之间的差”。来自API文档。

  4. 创建2个NSDate,其差异是要转换的NSTimeInterval。(如果您的NSTimeInterval来自比较2个NSDate,则不需要执行此步骤,甚至不需要NSTimeInterval)。

  5. 从NSDateComponents获取报价

样例代码

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

已知的问题

  • 只是对转换来说太多了,您是对的,但这就是API的工作方式。
  • 我的建议:如果您习惯使用NSDate和NSCalendar管理时间数据,则API将为您完成艰苦的工作。

4
绝对地,要做一些转换的方法很多,但是感觉很舒适,模块化并且非常灵活,请投票给此示例代码@Albaregar。
Rigo Vides

2
+1为了得到一个很好的完整答案,但是此代码非常昂贵。
尼克·韦弗

1
+1 ...一个警告。如果需要舍入小数秒,请小心使用这种代码风格。-[NSCalendar components:fromDate:toDate:options:]的默认行为在toD​​ate组件比fromDate提前31.5秒的情况下可能会弄乱-返回的组件的秒数字段将为31。NSWrapCalendarComponents有一个可选参数,但是根据我对此所做的(有限的)实验,它包装到最接近的秒数,而不是向上或向下取整。你的旅费可能会改变。
David Doyle

%ld如果您使用的是64位计算机。
Anoop Vaidya

5
发现这一点的人(例如Nick Weaver)将认为代码看起来很慢。不是。我正在做一个计时器应用程序,我只是针对Brian Briansey(和其他人)风格的东西测试了Albaregar的版本……令人惊讶的是,甚至在相对较慢的设备(4S)下每秒轮询100次(这是过大的杀伤力)。 )的处理器利用率相差不到1%。
mmc 2014年

42

所有这些看起来都比他们需要的复杂!这是将时间间隔转换为小时,分钟和秒的简短而甜美的方法:

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;

请注意,当您将浮点数放入int时,会自动获得floor(),但是如果感觉更好,可以将其添加到前两个中:-)


太棒了!我尝试了拉姆齐的代码,尽管似乎一秒钟。
uplearnedu.com 2013年

您在代码中缺少分号,但不允许我对其进行修改以解决此问题。
杰夫

我认为您的方法是最好的-简单,轻松地完成工作并“轻松”完成。完善。
BonanzaDriver 2014年

29

原谅我是一名堆栈处女...我不确定如何回复Brian Ramsay的回答...

对于59.5到59.99999之间的第二个值,使用round无效。在此期间,第二个值为60。改用trunc ...

 double progress;

 int minutes = floor(progress/60);
 int seconds = trunc(progress - minutes * 60);

1
实际上,只需将地板和行李箱/轮全部拆除即可。:)
InvulgoSoft

@StratFan能否请您增加几个小时的答案?
Shmidt

27

如果您的目标是iOS 8或OS X 10.10或更高版本,这将变得容易得多。新NSDateComponentsFormatter类允许您转换给定的NSTimeInterval的值(以秒为单位)转换为本地化字符串以显示给用户。例如:

目标C

NSTimeInterval interval = 326.4;

NSDateComponentsFormatter *componentFormatter = [[NSDateComponentsFormatter alloc] init];

componentFormatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional;
componentFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDropAll;

NSString *formattedString = [componentFormatter stringFromTimeInterval:interval];
NSLog(@"%@",formattedString); // 5:26

迅速

let interval = 326.4

let componentFormatter = NSDateComponentsFormatter()

componentFormatter.unitsStyle = .Positional
componentFormatter.zeroFormattingBehavior = .DropAll

if let formattedString = componentFormatter.stringFromTimeInterval(interval) {
    print(formattedString) // 5:26
}

NSDateCompnentsFormatter还允许此输出采用更长的形式。可以在NSHipster的NSFormatter文章中找到更多信息。而且,根据您已经在使用的类(如果不是NSTimeInterval),向格式化程序传递NSDateComponents,或两个NSDate对象的实例可能会更方便,这也可以通过以下方法来完成。

目标C

NSString *formattedString = [componentFormatter stringFromDate:<#(NSDate *)#> toDate:<#(NSDate *)#>];
NSString *formattedString = [componentFormatter stringFromDateComponents:<#(NSDateComponents *)#>];

迅速

if let formattedString = componentFormatter.stringFromDate(<#T##startDate: NSDate##NSDate#>, toDate: <#T##NSDate#>) {
    // ...
}

if let formattedString = componentFormatter.stringFromDateComponents(<#T##components: NSDateComponents##NSDateComponents#>) {
    // ...
}

这是创建足够本地化的字符串的正确方法
SwiftArchitect

1
这个答案比公认的答案更“客观-C”和有用。您不需要switchif else与此声明。NSDateComponentsFormatter照顾好一切。时,分,秒打印无后顾之忧。
rustyMagnet

17

伪造了Brian Ramsay的代码:

- (NSString*)formattedStringForDuration:(NSTimeInterval)duration
{
    NSInteger minutes = floor(duration/60);
    NSInteger seconds = round(duration - minutes * 60);
    return [NSString stringWithFormat:@"%d:%02d", minutes, seconds];
}

这不会本地化
-SwiftArchitect

7

这是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)
}

可以这样使用:

let (d,h,m,s) = durationsBySecond(seconds: duration)
println("time left: \(d) days \(h) hours \(m) minutes \(s) seconds")

6
    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);

输出:

timeLater: 22:27
timeLeft: 1 hours 29 minutes  59 seconds

它是隐蔽约会的一个非常完美的例子
ravinder521986

5

由于本质上是双重的...

除以60.0并提取整数部分和小数部分。

不可分割的部分将是分钟的总数。

再次将小数部分乘以60.0。

结果将是剩余的秒数。


3

请记住,最初的问题与字符串输出有关,而不是伪代码或单个字符串组成部分。

我想将其转换为以下字符串:“ 5:26”

许多答案都缺少国际化问题,大多数答案是手工进行的。都是20世纪...

不要自己做数学(快速4)

let timeInterval: TimeInterval = 326.4
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.unitsStyle = .positional
if let formatted = dateComponentsFormatter.string(from: timeInterval) {
    print(formatted)
}

5:26


利用图书馆

如果您确实想要单独的组件以及令人愉悦的代码,请查看SwiftDate

import SwiftDate
...
if let minutes = Int(timeInterval).seconds.in(.minute) {
    print("\(minutes)")
}

5


学分@mickmaccallum@polarwar为充分使用DateComponentsFormatter


0

我如何在Swift中做到这一点(包括将字符串格式显示为“ 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)

0

Swift 2版本

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"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.