13

How to parse string value like 12:02:21.3213 to NSTimeInterval? NSDateComponentsFormatter, available since iOS8, supports only formatting, not parsing.

Bartosz Hernas
  • 1,130
  • 1
  • 9
  • 17
  • 2
    Possible duplicate of [How can I convert string date to NSDate?](http://stackoverflow.com/questions/24777496/how-can-i-convert-string-date-to-nsdate) – rghome Feb 15 '16 at 11:35
  • @rghome: No, not a duplicate, at least not of *that* question. – "12:02:21.3213" here is a *duration* (which can be represented as a NSTimeInterval), not as a point in time (which would be an NSDate). – Martin R Feb 15 '16 at 11:52
  • Maybe not an exact duplicate. You can parse the time for 1st January 1970 and then get the interval for that date. I guess that is just about a separate answer in itself. – rghome Feb 15 '16 at 11:55
  • I wouldn't be posting both question and an answer if I would find a solution that satisfies me. I was using an appending time to 1st Jan 1970 but it all crapped itself when there were milliseconds. Additionally, I do not know how it would behave when duration would be more than 24h – Bartosz Hernas Feb 15 '16 at 12:31
  • 2
    I tried out NSDateFormatter. It accepts milliseconds, but not microseconds. It doesn't work for hours > 23, so it would appear that NSDateFormatter is not ideal, and you have, indeed, a good question. – rghome Feb 15 '16 at 20:05

3 Answers3

14

Here is how you can do it in Swift,

It works for values like 2:12:12, 02:01:23.123213

Swift 5 (by @Youstanzr):

extension String {
    func convertToTimeInterval() -> TimeInterval {
        guard self != "" else {
            return 0
        }

        var interval:Double = 0

        let parts = self.components(separatedBy: ":")
        for (index, part) in parts.reversed().enumerated() {
            interval += (Double(part) ?? 0) * pow(Double(60), Double(index))
        }

        return interval
    }
}

Swift 3 (by @Torre Lasley)

func parseDuration(_ timeString:String) -> TimeInterval {
    guard !timeString.isEmpty else {
        return 0
    }

    var interval:Double = 0

    let parts = timeString.components(separatedBy: ":")
    for (index, part) in parts.reversed().enumerated() {
        interval += (Double(part) ?? 0) * pow(Double(60), Double(index))
    }

    return interval
}

Swift 2

    func parseDuration(timeString:String) -> NSTimeInterval {
        guard !timeString.isEmpty else {
            return 0
        }
        
        var interval:Double = 0
        
        let parts = timeString.componentsSeparatedByString(":")
        for (index, part) in parts.reverse().enumerate() {
            interval += (Double(part) ?? 0) * pow(Double(60), Double(index))
        }
        
        return interval
    }
Bartosz Hernas
  • 1,130
  • 1
  • 9
  • 17
10

The solution provided by Bartosz Hernas worked for me, thank you!

For convenience, here it is for Swift 3:

func parseDuration(_ timeString:String) -> TimeInterval {
    guard !timeString.isEmpty else {
        return 0
    }

    var interval:Double = 0

    let parts = timeString.components(separatedBy: ":")
    for (index, part) in parts.reversed().enumerated() {
        interval += (Double(part) ?? 0) * pow(Double(60), Double(index))
    }

    return interval
}
Torre Lasley
  • 7,243
  • 3
  • 24
  • 12
6

Here is the Swift 5 version that I've made of @Bartosz answer

extension String {
    func convertToTimeInterval() -> TimeInterval {
        guard self != "" else {
            return 0
        }

        var interval:Double = 0

        let parts = self.components(separatedBy: ":")
        for (index, part) in parts.reversed().enumerated() {
            interval += (Double(part) ?? 0) * pow(Double(60), Double(index))
        }

        return interval
    }
}
Youstanzr
  • 605
  • 1
  • 8
  • 16