NSTimeInterval (초)을 분으로 변환하는 방법


104

seconds특정 이벤트에서 전달 된 금액이 있습니다. NSTimeInterval데이터 유형에 저장됩니다 .

나는 그것을 minutes및 로 변환하고 싶습니다 seconds.

예를 들어 "326.4"초가 있고 "5:26"문자열로 변환하고 싶습니다.

이 목표를 달성하는 가장 좋은 방법은 무엇입니까?

감사.

답변:


147

의사 코드 :

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

90
NSTimerInterval은 double의 typedef 일 뿐이라는 점도 언급 할 가치가 있다고 생각합니다.
Armentage

4
Albaregar의 답변을 참조하십시오 - 그것은이 (더 많은 코드하지만 더 유연하고 유지 보수) 일을 더 나은 방법입니다
benvolioT

1
그러나 그 코드는 매우 비쌉니다. 기간을 초 단위로 빠르게 변환하려면이 답변이 더 좋습니다.
SpacyRicochet 2012

2
이 답변은 1:60과 같은 내용을 제공합니다. 진실에 가까운 StratFan의 답변을보십시오. 그러나 바닥과 원형을 제거하고 집에 있어야합니다.
InvulgoSoft 2012

이 의견을 작성할 당시 아래 Mick MacCallum의 답변은 가장 많이 업데이트되고 네이티브 API를 사용하는 방식으로 작성된 것 같습니다.
토마스 나자렌코

183

간단한 설명

  1. Brian Ramsay의 대답은 분 단위로만 변환하려는 경우 더 편리합니다.
  2. Cocoa API를 원하면 NSTimeInterval을 분뿐만 아니라 일, 월, 주 등으로 변환하십시오. 이것은 좀 더 일반적인 접근 방식이라고 생각합니다.
  3. NSCalendar 방법 사용 :

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

    • "지정된 구성 요소를 사용하는 NSDateComponents 개체로 제공된 두 날짜 간의 차이를 반환합니다." 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-06-19

2
+1 철저한 답변을 위해이 코드는 상당히 비쌉니다.
Nick Weaver

1
+1 ... 한 가지주의 사항. 소수의 초를 반올림해야하는 경우이 스타일의 코드를 사용하는 데주의하십시오. -[NSCalendar components : fromDate : toDate : options :]의 기본 동작은 toDate 구성 요소가 fromDate보다 31.5 초 (예 :) 앞선 시나리오에서 엉망이 될 수 있습니다. 반환 된 구성 요소의 초 필드에는 31이 있습니다. NSWrapCalendarComponents의 선택적 매개 변수가 있지만이 작업을 수행 한 (제한된) 실험에서 반올림하거나 내림하지 않고 가장 가까운 초 단위로 래핑합니다. 귀하의 마일리지가 다를 수 있습니다.
David Doyle

%ld64 비트 머신을 사용하는 경우.
Anoop Vaidya 2013

5
이것을 발견하는 사람들 (예 : Nick Weaver)은 코드가 느릴 것 같다고 생각할 것입니다. 그렇지 않습니다. 저는 타이머 앱을 만들고 있으며 방금 Albaregar의 버전을 Brian Ramsey (및 기타) 스타일의 무언가에 대해 테스트했습니다 ... 놀랍게도 상대적으로 느린 장치 (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;

int에 float를 넣으면 자동으로 floor ()를 얻지 만 기분이 나아지면 처음 두 개에 추가 할 수 있습니다. :-)


대박! 나는 램지의 코드를 시도해 보았지만 잠시 나간 것 같았다.
uplearnedu.com

코드에 세미콜론이 누락되어 있지만 수정할 수 없습니다.
Jeef

나는 당신의 접근 방식이 가장 좋다고 생각합니다. 간단하고 일을 끝내고 진드기에 "가볍습니다". 완전한.
BonanzaDriver

29

스택 처녀가 된 것을 용서하십시오 ... Brian Ramsay의 답변에 어떻게 대답 해야할지 모르겠습니다 ...

라운드를 사용하면 59.5에서 59.99999 사이의 두 번째 값에 대해 작동하지 않습니다. 이 기간 동안 두 번째 값은 60이됩니다. 대신 trunc 사용 ...

 double progress;

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

1
실제로 바닥과 트렁크 / 라운드를 모두 제거하십시오. :)
InvulgoSoft 2010

@StratFan 답변에 시간을 추가해 주시겠습니까?
Shmidt

27

iOS 8 또는 OS X 10.10 이상을 타겟팅하는 경우 훨씬 쉬워졌습니다. 새 NSDateComponentsFormatter클래스를 사용하면 주어진 NSTimeInterval값을 초 단위로 현지화 된 문자열 로 변환 하여 사용자에게 표시 할 수 있습니다. 예를 들면 :

목표 -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또는 두 개의 NSDate개체 를 전달하는 것이 더 편리 할 수 있습니다. 다음 메서드를 통해서도 수행 할 수 있습니다.

목표 -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

위장 된 Brian Ramsay의 코드 :

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

이것은 현지화되지 않습니다
SwiftArchitect

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

날짜를 은밀한 그것의 정말 완벽한 예
ravinder521986

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.