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.