NSTimeInterval(秒)を分に変換する方法


104

seconds特定のイベントから渡された金額を受け取りました。NSTimeIntervalデータ型で保存されます。

私はに変換したいminutesseconds

たとえば、「326.4」秒あり、「5:26」という文字列に変換したいとします。

この目標を達成するための最良の方法は何ですか?

ありがとう。

回答:


147

疑似コード:

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

90
NSTimerIntervalはdoubleのtypedefにすぎないことにも言及する価値があると思います。
アーメンテージ

4
Albaregarの回答を参照してください。これは、これを行うためのより良い方法です(より多くのコードですが、より柔軟で、保守可能です)
benvolioT

1
ただし、そのコードは非常に高価です。秒単位で期間をすばやく変換するには、この回答の方が適しています。
SpacyRicochet

2
この答えは1:60のようなものを与えることに注意してください。真実に近いStratFanの答えを見てください。しかし、床と丸を外すと、家から解放されます。
InvulgoSoft

このコメントの執筆時点でのMick MacCallumの回答は、ネイティブAPIを使用する方法によって最も更新され、作成されているようです。
Tomasz Nazarenko 2017

183

簡単な説明

  1. ブライアンラムゼイの答えは、分に換算したいだけの場合に便利です。
  2. Cocoa APIが必要な場合は、NSTimeIntervalを分だけでなく、日、月、週などにも変換します...これはより一般的なアプローチだと思います
  3. NSCalendarメソッドを使用します。

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

    • 「指定されたコンポーネントを使用するNSDateComponentsオブジェクトとして、指定された2つの日付の差を返します」。APIドキュメントから。

  4. 変換するNSTimeIntervalが異なる2つのNSDateを作成します。(もし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 2010年

2
+1完全な答えとしては、このコードは非常に高価です。
Nick Weaver

1
+1 ... 1つの警告。小数秒を切り上げる必要がある場合は、このスタイルのコードの使用に注意してください。-[NSCalendarコンポーネント:fromDate:toDate:options:]のデフォルトの動作は、toDateコンポーネントが(たとえば)fromDateよりも31.5秒進んでいるシナリオでは混乱する可能性があります。返されるコンポーネントの秒フィールドには31があります。NSWrapCalendarComponentsのオプションのパラメーターがありますが、これを使って行った(制限された)実験から、四捨五入ではなく、最も近い秒に折り返されます。あなたのマイレージは異なる場合があります。
David Doyle

%ld64ビットマシンを使用している場合。
Anoop Vaidya 2013

5
これを見つけた人(Nick Weaverなど)は、コードが遅いように見えると思います。そうではありません。私はタイマーアプリを実行していて、ブライアンラムジー(およびその他)のスタイルの何かに対してアルバレガーのバージョンをテストしました...そして驚くべきことに、比較的遅いデバイス(4S )プロセッサー使用率の差は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;

floatをintに入れると、自動的にfloor()が取得されますが、気分が良ければ、最初の2つに追加することもできます:-)


驚くばかり!ラムゼイのコードを試してみましたが、少し遅れているようです。
uplearnedu.com 2013

コードにセミコロンがありませんが、修正して修正することはできません。
Jeef

私はあなたのアプローチが最も良いと思います-シンプルで、仕事を成し遂げ、そして目盛りを「軽く」します。完璧です。
BonanzaDriver 2014年

29

スタックの処女であることを許して...ブライアンラムゼイの答えに返信する方法がわかりません...

ラウンドの使用は、59.5から59.99999の間の2番目の値に対しては機能しません。この間、2番目の値は60になります。代わりにtruncを使用してください...

 double progress;

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

1
実際には、フロアとトランク/ラウンドを完全に削除します。:)
InvulgoSoft 2012

@StratFan回答に時間を追加していただけますか?
Shmidt、2015年

27

iOS 8またはOS X 10.10以上をターゲットにしている場合、これははるかに簡単になりました。新しいNSDateComponentsFormatterクラスを使用すると、指定さNSTimeIntervalれた値を秒単位でローカライズされた文字列に変換して、ユーザーを表示できます。例えば:

Objective-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、または2つのインスタンスを渡す方が便利な場合がありますNSDateオブジェクトのます。これは、次のメソッドでも実行できます。

Objective-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
この答えは、受け入れられた答えよりも「Objective-C」であり、有用です。あなたは必要としないswitchか、if elseこれとの声明。NSDateComponentsFormatterそれをすべて処理します。時間、分、秒が心配なく印刷されます。
rustyMagnet

17

ブライアンラムゼイのコード、疑似偽装:

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

これはローカライズされません
SwiftArchitect '10 / 10/17

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

日付を
隠す

5

基本的にはダブルなので...

60.0で割り、整数部と小数部を抽出します。

整数部分は分数です。

小数部をもう一度60.0で乗算します。

結果は残りの秒になります。


3

元の質問は、疑似コードや個々の文字列コンポーネントではなく、文字列出力に関するものであることに注意してください。

それを次の文字列に変換したい: "5:26"

多くの回答には国際化の問題が欠けており、ほとんどが手動で計算を行っています。まさに20世紀...

自分で計算しないでください(Swift 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"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.