NSTimeInterval to HH: mm: ss?


85

200.0 diyecek şekilde ayarlanmış bir NSTimeInterval'ım varsa, bunu 00:03:20'ye dönüştürmenin bir yolu var mı, onunla bir NSDate'i başlatıp sonra HH: mm: ss kullanarak NSDateFormatter kullanabileceğimi düşünüyordum. Sorum şu, bunu yapmanın hızlı bir yolu var mı yoksa numarayı kendim ayırıp kullanmam [NSString stringWithFormat: %02d:%02d:%02d, myHour, myMin, mySec]mı gerekiyor?

Yanıtlar:


198

NSDateFormatterBölme ve modulodan başka bir şey kullanmaya veya başka bir şeye gerek yok . NSTimeIntervalsadece çift içeren bir saniyedir.

Swift

func stringFromTimeInterval(interval: NSTimeInterval) -> String {
    let interval = Int(interval)
    let seconds = interval % 60
    let minutes = (interval / 60) % 60
    let hours = (interval / 3600)
    return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
}

Amaç-C

- (NSString *)stringFromTimeInterval:(NSTimeInterval)interval {
    NSInteger ti = (NSInteger)interval;
    NSInteger seconds = ti % 60;
    NSInteger minutes = (ti / 60) % 60;
    NSInteger hours = (ti / 3600);
    return [NSString stringWithFormat:@"%02ld:%02ld:%02ld", (long)hours, (long)minutes, (long)seconds];
}

Çok memnun oldum, düşündüğüm buydu ama sadece iOS SDK'nın bir parçası olarak zaten dahil edilmiş bir şeyi kaçırmadığımı kontrol etmek istedim.
fuzzygoat

1
":" Yalnızca İngilizce'de ve diğer bazı dillerde sınırlayıcı olarak çalıştığını belirtmek isterim. Örneğin, Fince "." Kullanır. - bunun gibi "15.02.59"
sgosha

@sgosha, tam olarak, normalde Apple bunlar için formatlayıcılar sağlama eğilimindedir. Bunun yerine biçimlendirme için yerelleştirilmiş bir dize kullanmalı mıyım?
Gerry Shaw

20
sınırlayıcıyı yerelleştirmediği için bu yanlış cevaptır (diğer yorumların da bahsettiği gibi). NSDateCompomentsFormatter'ı kullanarak, zaman aralığını tek bir satırda doğru şekilde biçimlendirebilirsiniz, örn NSDateComponentsFormatter().stringFromTimeInterval(NSTimeInterval(duration)). hızlı
Ilias Karim

4
Yerelleştirme ve ileride prova için doğru çözüm, NSDateComponentsFormatter'ı @jrc tarafından açıklandığı gibi kullanmaktır
voidref

103

İOS 8'de NSDateComponentsFormatter.

NSDateComponentsFormatter *dateComponentsFormatter = [[NSDateComponentsFormatter alloc] init];
NSLog(@"%@", [dateComponentsFormatter stringFromTimeInterval:200.0]);

"3:20" sonucunu verir.

NSDateComponentsFormatter *dateComponentsFormatter = [[NSDateComponentsFormatter alloc] init];
dateComponentsFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;
dateComponentsFormatter.allowedUnits = (NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond);
NSLog(@"%@", [dateComponentsFormatter stringFromTimeInterval:200.0]);

"0:03:20" sonucunu verir.


2
Güzel güncelleme. Ama eğer gerçekten bu kadar basit bir hesaplama ise, bu nesneyi kullanmak büyük bir ek yük olmaz mıydı (dinamik format olmadığı sürece)?
Julian F.Weinert

2
dizenin farklı yerel ayarlar vb. için doğru göründüğünden emin olmak için biçimlendirmeye ihtiyacınız var.
Max MacLeod

Gerçekten küçük bir yorum, ancak ObjectiveC sorusu için bir C fonksiyonu örneği vermek garip. Muhtemelen bunu ObjectiveC formatına dönüştürmeye değer mi?
Rilakkuma

Bana bir ton kod kurtardı! OrangeIRC için bu şekilde kullandım .
ahyattdev

17

Onmyway133'ün cevabının Swift 3 versiyonu :

import Foundation

func format(_ duration: TimeInterval) -> String {
    let formatter = DateComponentsFormatter()
    formatter.zeroFormattingBehavior = .pad
    formatter.allowedUnits = [.minute, .second]

    if duration >= 3600 {
        formatter.allowedUnits.insert(.hour)
    }

    return formatter.string(from: duration)!
}


print(format(12)) // 0:12
print(format(65)) // 1:05
print(format(1750)) // 29:10
print(format(3890)) // 1:04:50
print(format(45720)) // 12:42:00

DateComponentsFormatter oluşturmak, DateFormatter veya NumberFormatter gibi performans açısından pahalı mı?
Moshe

1
Bunun yerine bir saat değeri varsa ayarı, kontrol etme zeroFormattingBehaviorolmak [.dropLeading, .pad]daha iyi (daha az kod) bir seçenek olabilir.
MaddTheSane

Yorumlar yanlış görünüyor. Bu kod şu şekilde sonuçlanır: 00:12, 01:05, 29:10, 01:04:50, 12:42:00
Jordan H

10

Bazı ekstra kod satırları, ancak NSDateComponents kullanmanın daha kesin bir değer vereceğini düşünüyorum.

- (NSString *)getTimeRepresentationFromDate:(NSDate *)iDate withTimeInterval:(NSTimeInterval)iTimeInterval {
    NSString *aReturnValue = nil;
    NSDate *aNewDate = [iDate dateByAddingTimeInterval:iTimeInterval]; 

    unsigned int theUnits = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    NSCalendar *aCalender = [NSCalendar currentCalendar];
    NSDateComponents *aDateComponents = [aCalender components:theUnits fromDate:iDate toDate:aNewDate options:0];

    aReturnValue = [NSString stringWithFormat:@"%d:%d:%d", [aDateComponents hour], [aDateComponents minute], [aDateComponents second]];

    return aReturnValue;
}

Yukarıdaki yöntem, TimeInterval'in oluşturulduğu 2 tarihi kullanır. Ayrıca [NSDate tarihi] 'ni iDate parametresine varsayılan değer olarak geçirebilirsiniz.
Roshit

2
Bu, @ matthias-bauch tarafından kullanılan yöntemden ne şekilde "daha kesin"?
jb

1
bu yöntemle u saniye, saat, dakika, yani 60 cinsinden zaman aralığını alırken @ matthias-bauch'un cevabı size ondalık olarak verir, örneğin yeterli süre beklerseniz 2 dakika 19 saniye yerine 1 dakika 79 saniye görürsünüz
Ashish Pisey

Bu, kabul edilen çözümden çok daha iyi bir çözümdür. ":" Kullanımı hala uluslararasılaşma için bir sorundur, ancak en azından bu artık günler ve gün ışığından yararlanma sınırlarında sağlamdır.
evanflash

@AshishPisey Modulo operatörü 59'dan daha büyük her şeyi engeller.
Matthias Bauch

8

Gelen Swift 2 , IOS 8+ . Bu, yalnızca gerektiğinde saati göstermemizi sağlar

func format(duration: NSTimeInterval) -> String {
  let formatter = NSDateComponentsFormatter()
  formatter.zeroFormattingBehavior = .Pad

  if duration >= 3600 {
    formatter.allowedUnits = [.Hour, .Minute, .Second]
  } else {
    formatter.allowedUnits = [.Minute, .Second]
  }

  return formatter.stringFromTimeInterval(duration) ?? ""
}

Yani sahipsin

print(format(12)) // 0:12
print(format(65)) // 1:05
print(format(1750)) // 29:10
print(format(3890)) // 1:04:50
print(format(45720)) // 12:42:00

4
NSTimeInterval ti = 3667;
double hours = floor(ti / 60 / 60);
double minutes = floor((ti - (hours * 60 * 60)) / 60);
double seconds = floor(ti - (hours * 60 * 60) - (minutes * 60));

4

Swift 4

DateComponentsFormatter().string(from: <# TimeInterval #>)

ör .:

DateComponentsFormatter().string(from: 59.0)

3

Matthias Bauch'un önerisini "genişletmek" için, Swift'de bunu NSTimeInterval'in hesaplanan bir özelliği yapardım:

extension NSTimeInterval {
  var stringValue: String {
    let interval = Int(self)
    let seconds = interval % 60
    let minutes = (interval / 60) % 60
    let hours = (interval / 3600)
    return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
  }
}

Bunun avantajı, NSTimeIntervalgörünüm denetleyicinize veya bu işlevi başka yere koyduğunuz yere değil türe bağlı olmasıdır. Kullanmak için şuna benzer bir şey yaparsınız:

let timeInterval = NSDate().timeIntervalSinceDate(start)        
self.elapsedTimeLabel.text = timeInterval.stringValue

Teşekkürler Kenny! Benim durumumda onlara ayrı ayrı ihtiyacım vardı, bu yüzden uzantınıza ek değişkenler ekledim: "var seconds: Int {let interval = Int (self); let seconds = interval% 60; return seconds}" ve böylece dakikalar ve saatler için devam eder. Böylece bu kullanım şöyle olacaktır: print ("harcanan dakika: (timeInterval.minutes)")
Vitalii

3

@ Onmyway133 tarafından verilen cevaba göre Swift 4 sürümü burada:

func format(duration: TimeInterval) -> String {
    let formatter = DateComponentsFormatter()
    formatter.zeroFormattingBehavior = .pad

    if duration >= 3600 {
        formatter.allowedUnits = [.hour, .minute, .second];
    } else {
        formatter.allowedUnits = [.minute, .second];
    }

    return formatter.string(from: duration) ?? "";
}

0

doğrudan apple docs'dan: h dosyasında:

 @property(strong,nonatomic)NSDateComponentsFormatter *timerFormatter;

m dosyasında

@synthesize timerFormatter;

- (void)viewDidLoad {
[super viewDidLoad];
NSDateComponentsFormatter *timerFormatter = [[NSDateComponentsFormatter alloc] init];
timerFormatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional; 
//10:59 Positional THIS ONE DOES NOT SEEM TO WORK iOS<9 WHEN <1Minute JUST SHOWS 01, 10m 59s Abbreviated, 10min 59sec Short, 10minutes 59seconds Full ...
timerFormatter.allowedUnits = NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
}

NSTimeInterval timeInterval'inizi hh: mm: ss dizesine dönüştürmeniz gerektiğinde, şunu yapın:

NSString *txt=[timerFormatter stringFromTimeInterval:timeInterval];

0

Sanırım zamanlayıcı fraksiyonu durdurulmalı. Matthias'ın kodu bu sorunu saniyeler içinde oluştururken, ben Matthias'ınkinden biraz değiştirilmiş aşağıdakini kullanıyorum

    - (NSString *)stringFromTimeInterval:(NSTimeInterval)interval {
        int ti = (int) ceil(interval);
        int seconds = ti % 60;
        int minutes = (ti / 60) % 60;
        int hours = (ti / 3600);
        return [NSString stringWithFormat:@"%02d:%02d:%02d",hours, minutes, seconds];
    }

0

Onmyway133'ün cevabının Amaç C versiyonu

- (NSString*) formatTimeInterval:(NSTimeInterval) timeInterval {

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

    formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;

    if (timeInterval > 3600) {
        formatter.allowedUnits = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    } else {
        formatter.allowedUnits = NSCalendarUnitMinute | NSCalendarUnitSecond;
    }

    return [formatter stringFromTimeInterval:timeInterval];
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.