0
$\begingroup$

Problem: I have strings of form "[d1, d2]" or sometimes just [d1] where d1 and d2 denote "times". I'm trying to convert these strings to their Mathematica Around equivalent. So for example

"[30min, 1hr]"

should be converted to

Around[Quantity[45, "Minutes"], Quantity[15, "Minutes"]]

Attempt: The following code snippet seems as a potential starting point for this conversion

StringCases["[30min, 1hr]", x : NumberString :> ToExpression[x]]
(* {30, 1} *)

however it only grabs raw numbers and not time quantities.

$\endgroup$
4
  • $\begingroup$ Are the designators for time, such as "m" and "hr" known? Are there any cases of "d" (for day) or "w" for week or similar? $\endgroup$
    – Mark R
    Commented Jan 12, 2020 at 21:13
  • $\begingroup$ Mark R: Can we say that the designators should be anything that Wolfram's SemanticInterpretation picks up when parsing time lengths? $\endgroup$
    – George
    Commented Jan 12, 2020 at 21:19
  • $\begingroup$ I think the problem is that "m" is ambiguous. Is it "meters" or "minutes". In your context, it is clear but I don't know that SemanticInterpretation has a context (such as time) as a qualifier. I have code that I think does what you want but was trying to clarify before posting. $\endgroup$
    – Mark R
    Commented Jan 12, 2020 at 21:24
  • $\begingroup$ Mark R: In that case, I'll adjust my example to have min instead of m (though "m" is more convenient in my case). $\endgroup$
    – George
    Commented Jan 12, 2020 at 21:27

1 Answer 1

2
$\begingroup$

This might work for you.

timeRules = {"m" -> "Minutes", "hr" -> "Hour", "min" -> "Minutes", 
   "h" -> "Hour"};
ParseTime[timeString_] := 
  With[{numberString = First@StringCases[timeString, NumberString]}, 
   Quantity @@ {ToExpression@numberString, 
     StringDelete[timeString, numberString] /. timeRules}];
ParseTimeString[bracketedTimeString_] := 
  ParseTime[#] & /@ 
   StringSplit[bracketedTimeString, {"[", ",", ", ", "]"}];
ApproximateTime[bracketedTimeString_] := 
 With[{parsedTime = ParseTimeString[bracketedTimeString]}, 
  If[Length[parsedTime] > 1, 
   Around[Median[parsedTime], Median[parsedTime] - Min[parsedTime]], 
   First@parsedTime]]

Given an input of

aString = "[30m,1hr]"
ApproximateTime[aString]

It returns

Around[
Quantity[0.75, "Hours"], 
Quantity[15., "Minutes"]]

EDIT: Made a couple of minor changes so that I didn't assume the first element was the smallest and to handle the case where the string is something like this: "[20m]".

ApproximateTime["[20m]"]
(* Quantity[20, "Minutes"] *)

EDIT 2: More minor changes in case there are spaces after the comma. And a new test case.

ApproximateTime[#] & /@ {"[20m,1h]", "[30m,45m]", "[45m, 2h]"}
(* {Around[
Quantity[0.6666666666666666, "Hours"], 
Quantity[20., "Minutes"]], 
 Quantity[Around[37.5, 7.5], "Minutes"], Around[
Quantity[1.375, "Hours"], 
Quantity[37.5, "Minutes"]]} *)

$\endgroup$
0

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.