7

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.

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
Ooku
  • 891
  • 1
  • 6
  • 14

3 Answers3

7

A method based on AbsoluteTime:

AbsoluteTime /@ durations - AbsoluteTime["00:00:00"]
(* {594, 1884, 2407, 718, 831, 3752} *)
VLC
  • 9,818
  • 1
  • 31
  • 60
  • 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. – kirma Apr 05 '22 at 04:13
5

One method:

3600 FromDMS[ToExpression[StringSplit[#, ":"]]] & /@ durations
   {594, 1884, 2407, 718, 831, 3752}
J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
5

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

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371