web-dev-qa-db-ja.com

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

特定のイベントから渡されたsecondsの量があります。 NSTimeIntervalデータ型に保存されます。

minutessecondsに変換したい。

たとえば、「326.4」秒で、次の文字列「5:26」に変換したい。

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

ありがとう。

104

擬似コード:

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

簡単な説明

  1. Brian Ramsayからの回答は、分単位に変換する場合にのみ便利です。
  2. Cocoa APIがあなたのためにそれを行い、NSTimeIntervalを数分だけでなく日、月、週などに変換したい場合...これはより一般的なアプローチだと思います
  3. NSCalendarメソッドを使用します。

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

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

  4. 変換するNSTimeIntervalが異なるNSDateを2つ作成します。 (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があなたのために大変な仕事をします。
182
Albaregar

これらはすべて、必要以上に複雑に見えます!以下は、時間間隔を時間、分、秒に変換する短くて便利な方法です。

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つに追加できます:-)

41
Prasad

スタック処女であることを許してください...ブライアンラムゼイの答えにどう答えるかわからない...

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

 double progress;

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

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

Swift

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 *)#>];

Swift

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

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

偽装されたブライアンラムゼイのコード:

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

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")
8
    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
6
polarwar

それは本質的に二重だから...

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

整数部分は整数分です。

小数部分に再度60.0を掛けます。

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

5
Policywatcher

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

次の文字列に変換したい: "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


DateComponentsFormatterを適切に使用するための @ mickmaccallum および @ polarwar へのクレジット

3
SwiftArchitect

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
SilentDirge

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"
0
SPatel