13

Is there a simple way to compute the difference between two times (same day), so 11:30 am and 01:20 pm should lead to 110 min (or 1h 50min), for example? I saw the datenumber package but it only seems to compute day differences (so works on a larger scale). [I didn't include a minimal example as I don't have any elegant way how to start the problem except for (ugly?) string 'divide-and-conquer' approaches]

Okay, I just also discovered datetime which looks more promising. Nevertheless, I don't see how one can compute differences of time points with this package (or calc?)

Update After David's answer, I expanded the MWE to my original example and realized the following Runaway argument-problem:

\documentclass{article}

\newcommand*{\mystart}{11:30 am}
\newcommand*{\myend}{01:20 pm}

% duration
\def\duration#1#2{%
  \the\numexpr(\xduration#2\relax)-(\xduration#1\relax)\relax\ minutes}

\def\xduration#1:#2 #3m#4\relax{%
(#1)*60+#2\if p#3+720 \fi
}

% environment
\newenvironment{tbl}[3]{
  \begin{tabular}{ll}
    #1 & \duration{#2}{#3}\\
  \end{tabular}
}{}

\begin{document}
\begin{tbl}{Duration}{\mystart}{\myend}% Runaway argument? ! File ended while scanning use of \xduration.
%\begin{tbl}{Duration}{11:30 am}{01:20 pm}% works
\end{tbl}
\end{document}

How can this be avoided? [another pair of {} did not help]

  • 2
    Do you want the difference result as "110 minutes" or "1 hr 50 minutes"? – Steven B. Segletes Sep 25 '14 at 13:09
  • 2
    Convert the hour to minutes: (hour if pm + 12 fi)*60 + minutes; do the difference; convert back to hour and minutes. – egreg Sep 25 '14 at 13:13
  • @StevenB.Segletes Thanks, both are okay, whatever is more convenient. – Marius Hofert Sep 25 '14 at 13:18
  • 1
    To fix your problem, replace \xduration with \expandafter\xduration in the definition of \duration. (twice) – Steven B. Segletes Sep 25 '14 at 14:03
15
\documentclass{article}

\def\foo#1#2{%
  \the\numexpr(\xfoo#2\relax)-(\xfoo#1\relax)\relax\ minutes}

\def\xfoo#1:#2 #3m#4\relax{%
%(#1)*60+#2\if p#3+720 \fi
(#1)*60+#2\if p#3\ifnum#1=12 \else+720\fi\fi
}



\begin{document}

\foo{11:30 am}{01:20 pm}

\end{document}

If you want to expand the arguments before parsing, as in the edited MWE:

\documentclass{article}

\newcommand*{\mystart}{11:30 am}
\newcommand*{\myend}{01:20 pm}

% duration
\def\duration#1#2{%
  {\def\,{ }%
  \edef\tmp{%
   \noexpand\theminutes{%
   \noexpand\the
   \noexpand\numexpr
   (\noexpand\xduration#2\relax)-%
   (\noexpand\xduration#1\relax)\relax}}\tmp}}

\def\xduration#1:#2 #3m#4\relax{%
%(#1)*60+#2\if p#3+720\fi
 (#1)*60+#2\if p#3\ifnum#1=12 \else+720\fi\fi
}

\def\theminutes#1{%
#1\ minute\ifnum#1=1 \else s\fi}

% environment
\newenvironment{tbl}[3]{
  \begin{tabular}{ll}
    #1 & \duration{#2}{#3}\\
  \end{tabular}
}{}

\begin{document}
\begin{tbl}{Duration}{11:30 am}{01:20 pm}% works
\end{tbl}

\begin{tbl}{Duration}{\mystart}{\myend}% Runaway argument? ! File ended while scanning use of \xduration.
\end{tbl}

\begin{tbl}{Duration}{11:30\,am}{01:20\,pm}% works
\end{tbl}



\begin{tbl}{Duration}{12:30 pm}{03:00 pm} % works
\end{tbl}


\begin{tbl}{Duration}{11:30\,am}{11:31\,am}
\end{tbl}


\end{document}

enter image description here

  • I realized a strange error when I use the "duration" command inside a table/environment. I updated the post. Do you see how to avoid this error? – Marius Hofert Sep 25 '14 at 13:57
  • @MariusHofert nothing to do with tabular, I parse looking for : to split up the time and you hid that in a macro, if you need to expand macros before parsing for minutes it needs another line... – David Carlisle Sep 25 '14 at 14:04
  • Hi, thanks a lot, David. I just had to put a % after \edef\tmp{ to avoid a small horizontal space to be inserted. Works very well, thanks again. – Marius Hofert Sep 25 '14 at 14:10
  • 1
    @MariusHofert updated answer – David Carlisle Sep 25 '14 at 22:10
  • 1
    @SvendTveskæg updated – David Carlisle Nov 15 '14 at 16:08
9

Expanding on David's excellent answer, to give the alternative output, as

xx hour(s) xx minute(s).

REEDITED to use singular "minute" and "hour" if there is only 1 of them. Also, applied modulo fix when time was 12:xx (had to subtract 720 to treat 12 hour like 00 hour)

Here is the MWE (EDITED to expand the arguments, allowing them to be passed in macro form):

\documentclass{article}

\def\foo#1#2{\edef\tmp{\numfoo{#1}{#2}}\tmp\ minute%
  \ifnum\tmp=1\relax\else s\fi}

\def\xfoo#1:#2 #3m#4\relax{(#1)*60+#2\if p#3+720\fi\ifnum#1=12-720\fi}

\def\numfoo#1#2{%
  \the\numexpr(\expandafter\xfoo#2\relax)-(\expandafter\xfoo#1\relax)\relax}

\def\barr#1#2{%
  \edef\tmp{\the\numexpr((\numfoo{#1}{#2})-(30))/60\relax}%
  \tmp\ hour\ifnum\tmp=1\relax\else s\fi\ %
  \edef\tmp{\the\numexpr(\numfoo{#1}{#2})-((\numfoo{#1}{#2})-(30))/60*60}%
  \tmp\ minute\ifnum\tmp=1\relax\else s\fi%
}

\begin{document}
\foo{11:30 am}{01:20 pm} = \barr{11:30 am}{01:20 pm}

\foo{11:30 am}{12:31 pm} = \barr{11:30 am}{12:31 pm}

\foo{12:30 am}{12:31 pm} = \barr{12:30 am}{12:31 pm}

\foo{11:59 am}{12:00 pm} = \barr{11:59 am}{12:00 pm}

\def\starttime{11:30 am}
\def\endtime{03:20 pm}

\foo{\starttime}{\endtime} = \barr{\starttime}{\endtime}
\end{document}

enter image description here

  • Is it possible to use some sort of \if argument to get hour if it's 1 and hours if it's anything else? (The same with minute/minutes.) – Svend Tveskæg Nov 15 '14 at 15:47
  • @SvendTveskæg Done, and fixed bug when time involved "12:xx" – Steven B. Segletes Nov 15 '14 at 20:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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