3

I have a TimeInterval I had to turn it into a String so it could be added to the Dictionary that gets passed from Apple Watch to iPhone via WatchConnectivity.

Now that I have the String on the iPhone, I need to turn it back into a TimeInterval, but I can't seem to figure that out.

(I need to display this in a UILabel that shows the duration of the workout session.)

Any ideas?

For Example

Watch:

00:15:15 (hours, minutes, seconds) turns into "915.012948989868"

let myDouble = computeDurationOfWorkout(withEvents: hkWorkout?.workoutEvents, startDate: hkWorkout?.startDate, endDate: hkWorkout?.endDate)
let myDoubleString = String(myDouble)
durationVariableString = myDoubleString 

iPhone:

Need to turn "915.012948989868" back into 00:15:15

Mattia Righetti
  • 1,265
  • 1
  • 18
  • 31
SRMR
  • 3,064
  • 6
  • 31
  • 59
  • How about this: http://stackoverflow.com/questions/26794703/swift-integer-conversion-to-hours-minutes-seconds – toddg Nov 30 '16 at 16:31
  • Your question is very confusing. It seems you already have code to convert a `TimeInterval` to a string in the format hh:mm:ss. It seems you already have code to convert the string back into a `TimeInterval` (double). What exactly are you asking for help with? – rmaddy Nov 30 '16 at 16:36
  • @toddg I will check out that link, thanks! – SRMR Nov 30 '16 at 16:39
  • @rmaddy I don't see that I have code to convert the String back to a `TimeInterval`, which is what I'm looking for. But maybe I'm mistaken and you see something that I am totally missing, which could definitely be the case. Are you talking about the line `let myDouble = computeDurationOfWorkout(withEvents: hkWorkout?.workoutEvents, startDate: hkWorkout?.startDate, endDate: hkWorkout?.endDate)`? That part pulls from HealthKit, but when I'm on the iPhone I'm just trying to pull from a `String` that was passed to me. – SRMR Nov 30 '16 at 16:43
  • Do you want to just convert 915 to 00:15:15 ? – Rajat Nov 30 '16 at 16:48
  • Yes, I assumed your `computeDurationOfWorkout` was your code for converting the string back to a double. Especially since your question states that on the Watch you convert the string into the double. – rmaddy Nov 30 '16 at 16:48

3 Answers3

4

Using calendar.dateComponents you can convert 915 to 00:15:15

func stringFromTimeInterval (interval: String) -> String {
        let endingDate = Date()
        if let timeInterval = TimeInterval(interval) {
            let startingDate = endingDate.addingTimeInterval(-timeInterval)
            let calendar = Calendar.current

            var componentsNow = calendar.dateComponents([.hour, .minute, .second], from: startingDate, to: endingDate)
            if let hour = componentsNow.hour, let minute = componentsNow.minute, let seconds = componentsNow.second {
                return "\(hour):\(minute):\(seconds)"
            } else {
                return "00:00:00"
            }

        } else {
            return "00:00:00"
        }
    }
Rajat
  • 10,977
  • 3
  • 38
  • 55
  • Thanks for the response! This isn't quite the exact fit, because I need to pass in a `String` as an argument, not a `TimeInterval` as an argument. And then I need to return a `TimeInterval`, instead of return a `String`. Any thoughts? – SRMR Nov 30 '16 at 16:58
  • You need a function in which you pass 00:15:15 and it will return 915 ? – Rajat Nov 30 '16 at 16:59
  • A function where I pass in a `String` "915.012948989868", and get back a `TimeInterval` "00:15:15". Like `func timeIntervalFromString (string: String) -> TimeInterval` or something? – SRMR Nov 30 '16 at 17:03
  • 00:15:15 that is not a TimeInterval, **TimeInterval is always specified in seconds**, also you can convert TimeInterval to String in the above function – Rajat Nov 30 '16 at 17:04
  • "915.012948989868" is a `TimeInterval` as String though. Which is what I have. So I need to convert that String to a TimeInterval first though right? And then convert that TimeInterval into 00:15:15, right? – SRMR Nov 30 '16 at 17:10
  • Yes you need to convert String to TimeInterval – Rajat Nov 30 '16 at 17:14
  • Thanks I'll do that! – SRMR Nov 30 '16 at 17:18
  • 1
    @SRMR updated my answer, the function will take string now and return you string – Rajat Nov 30 '16 at 17:18
  • This solution has 1 flaw, but a simple one in the formatting - 0's are not padded out. To fix that you need some old fashion String(format:) calls. I implemented this as a TimeInterval extension - see below for my sample – Stephen Orr Jun 15 '18 at 11:12
3

This can be done as an extension to TimeInterval. Also this version correctly handles minutes / seconds < 10 by padding them.

extension TimeInterval {
    var formatted: String {
        let endingDate = Date()
        let startingDate = endingDate.addingTimeInterval(-self)
        let calendar = Calendar.current

        var componentsNow = calendar.dateComponents([.hour, .minute, .second], from: startingDate, to: endingDate)
        if let hour = componentsNow.hour, let minute = componentsNow.minute, let seconds = componentsNow.second {
            return "\(String(format: "%02d", hour)):\(String(format: "%02d", minute)):\(String(format: "%02d", seconds))"
        } else {
            return "00:00:00"
        }
    }
}

and handle the String -> TimeInterval conversion inline.

TimeInterval(intervalAsString).formatted
Stephen Orr
  • 291
  • 3
  • 7
2

Instead of turning the time interval into a string, instead turn it into an NSNumber that can be added to the Dictionary. An NSTimeInterval is simply a double, so you can cast it to and from a double easily.

let timeInterval: TimeInterval = 915.012948989868

let dict = ["TimeIneterval": NSNumber(value: timeInterval)]

if let extractedTimeInterval: TimeInterval = dict["TimeIneterval"] as? TimeInterval {

    print(extractedTimeInterval)
}
dlbuckley
  • 685
  • 1
  • 5
  • 14
  • Thanks for the response! I will give this a try. Once I pass the `NSNumber` via the Dictionary to the iPhone, once I've got the `NSNumber` on the iPhone would I just need to convert it back to a `TimeInterval` then? – SRMR Nov 30 '16 at 17:00