I'm trying to write a command in LaTeX that takes a string such as 8:00A and converts it into the number of minutes, as part of a script to draw a class schedule using TikZ. However, I'm running into some issues – it seems that LaTeX doesn't actually evaluate the contents of a command.
My command is currently:
\newcommand{\timetominutes}[1]{
\IfSubStr{#1}{P}{720}{0}+\IfSubStr{#1}{P}{\StrBetween{#1}{:}{P}}{\StrBetween{#1}{:}{A}}+60*\StrBefore{#1}{:}
}
If you print out the text from it, it will correctly calculate the number of minutes from midnight. However, if used inside another function, it becomes apparent that it doesn't actually run any of those commands – it merely returns text including those commands. So if I write:
\myfunc{\timetominutes{8:00A}}
Instead of \myfunc
seeing something useful like 0+00+60*8
, it sees \IfSubStr{8:00A}{P}{720}{0}+\IfSubStr{8:00A}{P}{\StrBetween{8:00A}{:}{P}}{\StrBetween{8:00A}{:}{A}}+60*\StrBefore{8:00A}{:}
. This is absolutely useless to me and I can't seen to find a way to force LaTeX to execute subcommands before the main one. I assume there's a way to do it, but LaTeX documentation is scarce and I can't seem to find anything.
Alternatively, if there's a way to get LaTeX to stop complaining about too many }
s (when I have the correct number), that could work.
Best Answer
Unfortunately, no. As the xstring package states:
(Section 3.2 of xtring_doc_en.pdf.)
This "expandable" concept, if you're not familiar with it, is quite a hairy subject in TeX. Simply put, something that is not expandable cannot be evaluated as an argument. Anything that uses an assignment somewhere is guaranteed not to be expandable in most TeX varieties, but other non-expandable triggers exist as well. The solution to such problems is rather difficult for anyone that's not familiar with the inner workings of TeX's "mouth" (the part of TeX that handles things like expansion).
Hint: If the LaTeX code is generated by a script: use the script to convert the time expressions, because just about any programming language is easier to use than TeX when it comes to string manipulation. (Or just about anything else for that matter.)
The xstring package does hint at a way out: You can store the result of most operations in a variable, by adding
[\variable]
to the end of the calls. This means you'd need to rewrite\timetominutes
to something that builds up the result piece by piece, and then store that result in a command sequence for use later on.Usage:
Note the use of
\expandafter
, which tells TeX to do a simple one-level expansion (evaluation) of a command sequence after the next. If you didn't use the two\expandafter
s, you'd get\somevar
as an argument to\myfunc
, not48
.(Caution: ugly TeX code ahead!)
\def
is the TeX primitive corresponding to LaTeX's\newcommand
/\renewcommand
.\edef
means Expanding\def
, which evaluates the definition before assigning the result to a command sequence.\numexpr
evaluates a simple number expression, like x + m + h * 60 created by the command above.It is also possible to calculate the result immediately as a number, without building up the formula, by using integer arithmetic. But that would make the code even more remote from your original intent.
It is possible to do these string manipulations through TeX itself, without using the
xstring
package (even expandible in this particular case). But that's pretty low level stuff, which cannot easily be repeated if you're not a TeX wizzard.