How to convert a time pattern from a string to TimeInterval in Swift?

588 Views Asked by At

I have an array of strings that contains a time pattern (e.g '30 min'):

let arrayOfStrings: [String] = ["Episode 1 - 23 min", "Episode 2 - 42 min", "Episode 3 - 45 min"] 

func convertToTimeInterval(from string: String) -> TimeInterval {
    // logic here...
    return timeInterval // Double
}

So using such a method, I want from the results:

arrayOfStrings.forEach { string in 
   print(convertToTimeInterval(from: string))
}

// Prints
1380 // timeinterval from "23 min"
2520 // timeinterval from "42 min"
2700 // timeinterval from "45 min"
  • I have tried splitting from the the 'min' character but the problem is that it has to support multiple language format. So there is no way to know in advance the character to split from.
  • I have also tried getting the CharacterSet.separatedBy but the string can contains multiple decimal that have nothing to do with the time (e.g Episode 1)

Thanks for your help!

2

There are 2 best solutions below

0
workingdog support Ukraine On

you could try this approach, where each string in the array is split into sections, and the minutes extracted and returned as a Double/TimeInterval.

This should (not tested) cater for multiple languages that uses Western Arabic numerals

let arrayOfStrings: [String] = ["Episode 1 - 23 min", "Episode 2 - 42 min", "Episode 3 - 45 min"]

arrayOfStrings.forEach { string in
     let t = convertToTimeInterval(from: string)
     print("--> timeInterval: \(t) minutes or \(t * 60) seconds")
}

func convertToTimeInterval(from string: String) -> TimeInterval {
    if let last = string.split(separator: "-").last {
        let term2 = last.split(separator: " ")
        if let minutes = term2.first {
            if let result = Double(minutes.trimmingCharacters(in: .whitespacesAndNewlines)) {
                return result
            }
        }
    }
    return 0.0  // <-- adjust as desired
}
0
vadian On

A rather underestimated but powerful API in Objective-C and Swift is (NS)Scanner.

Assuming there is always a hyphen and a whitespace character before the duration value just scanUpTo "- " then scan the pattern and then scan the numeric value as Double and multiply it with 60.

func convertToTimeInterval(from string: String) -> TimeInterval? {
    let scanner = Scanner(string: string)
    scanner.scanUpToString("- ")
    scanner.scanString("- ")
    guard let duration = scanner.scanDouble() else { return nil }
    return duration * 60.0
}

Or – a bit more elaborate – with NSRegularExpression. The pattern captures one or more digits after " - "

func convertToTimeInterval(from string: String) -> TimeInterval? {
    let regex = try! NSRegularExpression(pattern: #"\s-\s(\d+)"#)
    guard let firstMatch = regex.firstMatch(in: string, range: NSRange(string.startIndex..., in: string)) else { return nil }
    let durationRange = Range(firstMatch.range(at: 1), in: string)!
    return Double((string[durationRange]))! * 60.0
}

However it becomes more convenient with the new Regex API introduced in Swift 5.7

func convertToTimeInterval(from string: String) -> TimeInterval? {
    let regex = Regex {
        " - "
         Capture { OneOrMore(.digit) } transform: {
             Double($0)! * 60.0
         }
    }
    return string.firstMatch(of: regex)?.output.1
}