NSTimeInterval ถึง HH: mm: ss?


85

ถ้าฉันมี NSTimeInterval ที่ตั้งค่าเป็น 200.0 มีวิธีแปลงเป็น 00:03:20 ได้ไหมฉันคิดว่าจะเริ่ม NSDate ได้จากนั้นใช้ NSDateFormatter โดยใช้ HH: mm: ss คำถามของฉันคือมีวิธีที่รวดเร็วในการทำเช่นนี้หรือไม่ฉันต้องเลิกหมายเลขตัวเองและการใช้งาน[NSString stringWithFormat: %02d:%02d:%02d, myHour, myMin, mySec]?

คำตอบ:


198

ไม่จำเป็นต้องใช้NSDateFormatterหรือสิ่งอื่นใดนอกจากการหารและโมดูโล NSTimeIntervalเป็นเพียงเสี้ยววินาทีที่มี

รวดเร็ว

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

วัตถุประสงค์ -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];
}

ชื่นชมมากนั่นคือสิ่งที่ฉันคิด แต่ฉันแค่ต้องการตรวจสอบว่าฉันไม่ได้พลาดบางสิ่งที่รวมอยู่ใน iOS SDK แล้ว
fuzzygoat

1
ฉันต้องการชี้ให้เห็นว่า ":" ทำงานเป็นตัวคั่นเฉพาะในภาษาอังกฤษและภาษาอื่น ๆ ตัวอย่างเช่นภาษาฟินแลนด์ใช้ "." - แบบนี้ "15.02.59"
sgosha

@sgosha ตามปกติแล้ว Apple มักจะจัดหาฟอร์แมตสำหรับสิ่งเหล่านี้ ฉันควรใช้สตริงที่แปลเป็นภาษาท้องถิ่นสำหรับการจัดรูปแบบหรือไม่
Gerry Shaw

20
นี่เป็นคำตอบที่ไม่ถูกต้องเนื่องจากไม่ได้แปลตัวคั่น (ตามที่ความคิดเห็นอื่น ๆ กล่าวถึง) การใช้ NSDateCompomentsFormatter คุณสามารถจัดรูปแบบช่วงเวลาของคุณได้อย่างถูกต้องในบรรทัดเดียวเช่นNSDateComponentsFormatter().stringFromTimeInterval(NSTimeInterval(duration))ในรวดเร็ว
Ilias Karim

4
สำหรับการแปลและการพิสูจน์ในอนาคตวิธีแก้ไขที่ถูกต้องคือใช้ NSDateComponentsFormatter ตามที่ @jrc
voidref

103

บน iOS 8 ให้ใช้NSDateComponentsFormatterไฟล์.

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

เอาต์พุต "3:20"

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

เอาต์พุต "0:03:20"


2
การปรับปรุงที่ดี แต่ถ้ามันเป็นเพียงการคำนวณธรรมดา ๆ จริง ๆ จะไม่ใช้วัตถุเหล่านี้เป็นค่าใช้จ่ายขนาดใหญ่ (ตราบเท่าที่ไม่มีรูปแบบไดนามิกเกี่ยวข้อง)?
Julian F.Winert

2
คุณต้องจัดรูปแบบเพื่อให้แน่ใจว่าสตริงปรากฏอย่างถูกต้องสำหรับสถานที่ต่างๆเป็นต้น
Max MacLeod

ความคิดเห็นเล็ก ๆ น้อย ๆ แต่เป็นเรื่องแปลกที่จะยกตัวอย่างฟังก์ชัน C สำหรับคำถาม ObjectiveC อาจคุ้มค่าที่จะเปลี่ยนเป็นรูปแบบ ObjectiveC?
Rilakkuma

ช่วยฉันรหัสมากมาย! นี่คือวิธีที่ผมใช้มันสำหรับ OrangeIRC
ahyattdev

17

คำตอบของonmyway133เวอร์ชันSwift 3 :

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 ประสิทธิภาพสูงเช่น DateFormatter หรือ NumberFormatter หรือไม่
Moshe

1
แทนที่จะตรวจสอบว่ามีค่าชั่วโมงหรือไม่การตั้งค่าzeroFormattingBehaviorเป็น[.dropLeading, .pad]อาจเป็นตัวเลือกที่ดีกว่า (รหัสน้อยกว่า)
MaddTheSane

ความคิดเห็นดูเหมือนจะไม่ถูกต้อง รหัสนี้ให้ผลลัพธ์ใน: 00:12, 01:05, 29:10, 01:04:50, 12:42:00
Jordan H

10

โค้ดพิเศษบางบรรทัด แต่ฉันรู้สึกว่าการใช้ NSDateComponents จะให้ค่าที่แม่นยำกว่า

- (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;
}

วิธีการข้างต้นใช้ 2 วันที่ซึ่งใช้สร้าง TimeInterval คุณยังสามารถส่ง [NSDate date] ไปยังพารามิเตอร์ iDate เป็นค่าเริ่มต้น
Roshit

2
วิธีนี้ "แม่นยำกว่า" ที่ @ matthias-bauch ใช้ในทางใด
jb

1
ด้วยวิธีนี้คุณจะได้รับช่วงเวลาเป็นวินาทีชั่วโมงนาทีเช่นในรูปของ 60 ในขณะที่คำตอบของ @ matthias-bauch จะให้คุณในรูปทศนิยมเช่นถ้าคุณรอเวลาให้เพียงพอคุณจะเห็น 1 นาที 79 วินาทีแทนที่จะเป็น 2 นาที 19 วินาที
Ashish Pisey

นี่เป็นทางออกที่ดีกว่าโซลูชันที่ได้รับการยอมรับมาก การใช้ ":" ยังคงเป็นปัญหาสำหรับการทำให้เป็นสากล แต่อย่างน้อยก็ใช้ได้ดีในช่วงวันอธิกสุรทินและขอบเขตการออมแสง
evanflash

@AshishPisey ตัวดำเนินการ modulo ป้องกันสิ่งที่ใหญ่กว่า 59
Matthias Bauch

8

ในสวิฟท์ 2 , iOS 8 สิ่งนี้ทำให้แน่ใจว่าเราจะแสดงชั่วโมงเมื่อจำเป็นเท่านั้น

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) ?? ""
}

คุณมี

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



3

เพื่อ "ขยาย" คำแนะนำของ Matthias Bauch ใน Swift ฉันจะทำให้สิ่งนี้เป็นคุณสมบัติที่คำนวณได้ของ NSTimeInterval:

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

ข้อดีของสิ่งนี้คือมันแนบมากับNSTimeIntervalประเภทไม่ใช่ตัวควบคุมมุมมองของคุณหรือที่ใดก็ตามที่คุณใส่ฟังก์ชันนั้น ในการใช้คุณจะต้องทำสิ่งต่อไปนี้:

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

ขอบคุณ Kenny! ในกรณีของฉันฉันต้องการมันแยกกันดังนั้นฉันจึงเพิ่มตัวแปรเพิ่มเติมในส่วนขยายของคุณ: "var seconds: Int {let interval = Int (self); let seconds = interval% 60; return seconds}" ไปเรื่อย ๆ เป็นนาทีและชั่วโมง ดังนั้นการใช้งานจะเป็น: พิมพ์ ("นาทีที่ใช้: (timeInterval.minutes)")
Vitalii

3

จากคำตอบของ @ onmyway133 นี่คือเวอร์ชัน Swift 4:

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

ตรงจาก apple docs: ในไฟล์ h:

 @property(strong,nonatomic)NSDateComponentsFormatter *timerFormatter;

ในไฟล์ m

@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 เป็น hh: mm: ss string ให้ทำสิ่งนี้:

NSString *txt=[timerFormatter stringFromTimeInterval:timeInterval];

0

ฉันเดาว่าเศษส่วนของตัวจับเวลาควรจะหยุดลง เนื่องจากโค้ดของ Matthias กำลังสร้างปัญหานั้นในไม่กี่วินาทีฉันจึงใช้สิ่งต่อไปนี้ที่แก้ไขเล็กน้อยจาก Matthias

    - (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รุ่นObjective C

- (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];
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.