# Parsing time interval strings as “Uncertain” Time Intervals

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.

• 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? – Mark R Jan 12 '20 at 21:13
• Mark R: Can we say that the designators should be anything that Wolfram's SemanticInterpretation picks up when parsing time lengths? – George Jan 12 '20 at 21:19
• 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. – Mark R Jan 12 '20 at 21:24
• Mark R: In that case, I'll adjust my example to have min instead of m (though "m" is more convenient in my case). – George Jan 12 '20 at 21:27

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"]]} *)