7
$\begingroup$

I have a list of time durations, which are strings of the form: "hh:mm:ss". Here's a sample for you to play with:

durations = {"00:09:54", "00:31:24", "00:40:07", "00:11:58", "00:13:51", "01:02:32"}

I want to convert all of these into numbers in seconds, so that I can actually do useful things with this data!

How would I go about doing this? There must be some way to get Mathematica to extract the relevant things from each string.

Thanks.

Edit: I'm surprised that there doesn't seem to be a question related to this already - but it may be that I was using the wrong search terms.

$\endgroup$

3 Answers 3

7
$\begingroup$

A method based on AbsoluteTime:

AbsoluteTime /@ durations - AbsoluteTime["00:00:00"]
(* {594, 1884, 2407, 718, 831, 3752} *)
$\endgroup$
1
  • $\begingroup$ Although this produces correct answers, probably it would be adherent to the current Wolfram Language date & time toolset to do QuantityMagnitude[TimeObject /@ durations - TimeObject[{0}], "Seconds"] - where TimeObjects don't get dates assigned to them, and where you could also control the measurement unit in a more obvious manner. $\endgroup$
    – kirma
    Apr 5, 2022 at 4:13
5
$\begingroup$

One method:

3600 FromDMS[ToExpression[StringSplit[#, ":"]]] & /@ durations
   {594, 1884, 2407, 718, 831, 3752}
$\endgroup$
5
$\begingroup$

You didn't specify that performance is important but I decided to examine that aspect.

First I generate a list of 10,000 durations:

durations = 
  ToString@Row[#, ":"] & /@ 
   Map[IntegerString[#, 10, 2] &, 
    RandomInteger[{0, 24}, {10000, 3}], {2}];

I then time each of the existing solutions (using timeAvg, posted many times before):

AbsoluteTime /@ durations - AbsoluteTime["00:00:00"] // timeAvg

7.722

3600 FromDMS[ToExpression[StringSplit[#, ":"]]] & /@ durations // timeAvg

0.078

We see that at least with my test set and on my machine the second method is more than two orders of magnitude faster than the first, but I think we can do better:

FromDigits[#, 60] & /@ Map[FromDigits, StringSplit[durations, ":"], {2}] // timeAvg

0.02868

By using the undocumented function StringToDouble we can eek out a bit more:

timeAvg[
  FromDigits[#, 60] & /@ Map[Internal`StringToDouble, StringSplit[durations, ":"], {2}]
]

0.02248

This last method returns Reals instead of Integers, if that matters, but the time taken to Round is negligible:

seconds = 
  FromDigits[#, 60] & /@ Map[Internal`StringToDouble, StringSplit[durations, ":"], {2}];

Round[seconds] // timeAvg

0.00011488

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.