11

I'm looking for a package, or even a macro that allows me to simply write duration calculations for young students. Like for example this (Lebossé-Hemery 1957 classe de sixième):

Lebossé-Hémery 1957 classe de sixième

I prefer this notation updated with min for minute (and not m).

I found this code: http://forum.mathematex.net/latex-f6/module-sinuitx-et-le-temps-t11198.html#p108990

\documentclass{article}
\usepackage{ifmtarg}
\usepackage{siunitx}
\sisetup{number-unit-separator=~}
\makeatletter
\newcommand{\sitime}[1]{\sitime@aux#1;;;\@nil}
\def\sitime@aux#1;#2;#3;#4\@nil{%
  \@ifmtarg{#1#2#3}%
  {%
    \PackageError{siunitx (modified)}%
                 {Empty \string\sitime\space argument}{}%
  }%
  {%
    \@ifmtarg{#1}{}{\SI{#1}{\hour}\@ifmtarg{#2#3}{}{\csname l_siunitx_number_unit_separator_tl\endcsname}}%
    \@ifmtarg{#2}{}{\SI{#2}{\minute}\@ifmtarg{#3}{}{\csname l_siunitx_number_unit_separator_tl\endcsname}}%
    \@ifmtarg{#3}{}{\SI{#3}{\second}}%
  }%
}
\makeatother
\newcommand{\sep}{\qquad}
\begin{document}

$\sitime{10;7;12}-\sitime{9;13;8}$

\end{document}

It gives this, the spacing between hours and minutes are poorly managed, but the macro is convenient:

screenshot

  1. Is there a package that allows this to be done natively?
  2. Any ideas to improve this macro?
  3. Another macro?
7

You can have a friendly syntax:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\hms}{ >{\SplitArgument{2}{;}}m }
 {
  \ensuremath{\andrec_hms:nnn #1}
 }

\cs_new_protected:Nn \andrec_hms:nnn
 {
  \group_begin:
  \bool_set_false:N \l__andrec_hms_thinspace_bool
  \__andrec_hms_print:nn { 0#1 } { h }
  \tl_if_novalue:nTF { #2 }
   {
    \__andrec_hms_print:nn { 0 } { m }
   }
   {
    \__andrec_hms_print:nn { 0#2 } { m }
   }
  \tl_if_novalue:nTF { #3 }
   {
    \__andrec_hms_print:nn { 0 } { s }
   }
   {
    \__andrec_hms_print:nn { 0#3 } { s }
   }
  \group_end:
}
\cs_new_protected:Nn \__andrec_hms_print:nn
 {
  \int_compare:nT { #1 != 0 }
   {
    \bool_if:NT \l__andrec_hms_thinspace_bool { \, }
    \int_eval:n { #1 } \, \mathrm{#2}
    \bool_set_true:N \l__andrec_hms_thinspace_bool
   }
 }
\ExplSyntaxOff

\begin{document}

$\hms{7;40;21}+\hms{3;17;5}+\hms{2;4;20}$

$\hms{12;41;}+\hms{0;47;20}+\hms{7;0;37}$

$\hms{5;12;45}-\hms{4;9}$

\end{document}

For a missing value you can use 0 or nothing; a trailing missing value can be omitted altogether; so for 2 hours you can say \hms{2}, for 2 hours and 2 minutes \hms{2;2}.

enter image description here

With a separator that can be set or reset at runtime, and also chosen as an optional argument:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[french]{babel}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\hms}{ o m }
 {
  \ensuremath
   {
    \IfNoValueTF { #1 }
     {
      \andrec_hms:Ve \l_andrec_hms_sep_str { \tl_to_str:n { #2 } }
     }
     {
      \andrec_hms:ee { \tl_to_str:n { #1 } } { \tl_to_str:n { #2 } }
     }
   }
 }
\NewDocumentCommand{\sethmssep}{m}
 {
  \str_set:Nn \l_andrec_hms_sep_str { #1 }
 }

\cs_new_protected:Nn \andrec_hms:nn
 {
  \group_begin:
  \seq_set_split:Nnn \l__andrec_hms_seq { #1 } { #2 }
  % normalize the sequence to have three (or more!) items
  \int_compare:nT { \seq_count:N \l__andrec_hms_seq = 1 }
   {
    \seq_put_right:Nn \l__andrec_hms_seq { 0 }
   }
  \int_compare:nT { \seq_count:N \l__andrec_hms_seq = 2 }
   {
    \seq_put_right:Nn \l__andrec_hms_seq { 0 }
   }
  % print
  \bool_set_false:N \l__andrec_hms_thinspace_bool
  \__andrec_hms_print:nn { 1 } { h }
  \__andrec_hms_print:nn { 2 } { m }
  \__andrec_hms_print:nn { 3 } { s }
  \group_end:
}
\cs_generate_variant:Nn \andrec_hms:nn { Ve,ee }

\cs_new_protected:Nn \__andrec_hms_print:nn
 {
  \int_compare:nF { 0\seq_item:Nn \l__andrec_hms_seq { #1 } = 0 }
   {
    \bool_if:NT \l__andrec_hms_thinspace_bool { \, }
    \int_eval:n { 0\seq_item:Nn \l__andrec_hms_seq { #1 } } \, \mathrm{#2}
    \bool_set_true:N \l__andrec_hms_thinspace_bool
   }
 }
\ExplSyntaxOff

\sethmssep{:}

\begin{document}

$\hms{7:40:21}+\hms[;]{3;17;5}+\hms{2:4:20}$

\sethmssep{;}

$\hms{12;41;}+\hms{0;47;20}+\hms{7;0;37}$

\sethmssep{,}

$\hms{5,12,45}-\hms[;]{4;9}$

\end{document}

The output is the same. Using “stringifications”, we overcome the problems with babel.

So long as you don't want negative numbers, here's a modification that allows decimal numbers in the input. Note that you have to input the figures with a decimal point nontheless, but the output can be made to respect the locale.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[french]{babel}
\usepackage{xparse}
\usepackage{siunitx}

\sisetup{locale=FR}

\ExplSyntaxOn

\NewDocumentCommand{\hms}{ o m }
 {
  \ensuremath
   {
    \IfNoValueTF { #1 }
     {
      \andrec_hms:Ve \l_andrec_hms_sep_str { \tl_to_str:n { #2 } }
     }
     {
      \andrec_hms:ee { \tl_to_str:n { #1 } } { \tl_to_str:n { #2 } }
     }
   }
 }
\NewDocumentCommand{\sethmssep}{m}
 {
  \str_set:Nn \l_andrec_hms_sep_str { #1 }
 }

\cs_new_protected:Nn \andrec_hms:nn
 {
  \group_begin:
  \seq_set_split:Nnn \l__andrec_hms_seq { #1 } { #2 }
  % normalize the sequence to have three (or more!) items
  \int_compare:nT { \seq_count:N \l__andrec_hms_seq = 1 }
   {
    \seq_put_right:Nn \l__andrec_hms_seq { 0 }
   }
  \int_compare:nT { \seq_count:N \l__andrec_hms_seq = 2 }
   {
    \seq_put_right:Nn \l__andrec_hms_seq { 0 }
   }
  % print
  \bool_set_false:N \l__andrec_hms_thinspace_bool
  \__andrec_hms_print:nn { 1 } { h }
  \__andrec_hms_print:nn { 2 } { m }
  \__andrec_hms_print:nn { 3 } { s }
  \group_end:
}
\cs_generate_variant:Nn \andrec_hms:nn { Ve,ee }

\cs_new_protected:Nn \__andrec_hms_print:nn
 {
  \fp_compare:nF { 0\seq_item:Nn \l__andrec_hms_seq { #1 } = 0 }
   {
    \bool_if:NT \l__andrec_hms_thinspace_bool { \, }
    \num{\fp_eval:n { 0\seq_item:Nn \l__andrec_hms_seq { #1 } }} \, \mathrm{#2}
    \bool_set_true:N \l__andrec_hms_thinspace_bool
   }
 }
\ExplSyntaxOff

\sethmssep{:}

\begin{document}

$\hms{1.5::}=\num{1.5}\times\hms{:60:}=\hms{:90:}$ % new

$\hms{7:40:21}+\hms[;]{3;17;5}+\hms{2:4:20}$

\sethmssep{;}

$\hms{12;41;}+\hms{0;47;20}+\hms{7;0;37}$

\sethmssep{,}

$\hms{5,12,45}-\hms[;]{4;9}$

\end{document}

enter image description here

  • Thank you for your interest in this question. Is it possible to make the separator an option (local or global) so that I can define : or ; or any other symbol as separator? – AndréC Oct 11 at 16:28
  • 1
    @AndréC You're looking for trouble, as you know that : is a nuisance when babel-french is used. – egreg Oct 11 at 16:46
  • Yes, that's right, I forgot that. To write a question here, I wrongly Americanize my code. – AndréC Oct 11 at 16:59
  • @AndréC Well, a bit more complicated, but it could be done. See edit. – egreg Oct 11 at 17:19
  • 1
    Yes, it works perfectly – AndréC Oct 11 at 17:44
11

Just slightly modifying your code:

    \documentclass{article}
    \usepackage{ifmtarg}
    \usepackage{siunitx}
    \sisetup{number-unit-separator=\,}
    \makeatletter
    \newcommand{\sitime}[1]{\sitime@aux#1;;;\@nil}
    \def\sitime@aux#1;#2;#3;#4\@nil{%
      \@ifmtarg{#1#2#3}%
      {%
        \PackageError{siunitx (modified)}%
                     {Empty \string\sitime\space argument}{}%
      }%
    {%
    \@ifmtarg{#1}{}{\SI{#1}{\hour}\@ifmtarg{#2#3}{}{\csname l_siunitx_number_unit_separator_tl\endcsname}}%
    \@ifmtarg{#2}{}{~ \SI{#2}{\minute}\@ifmtarg{#3}{}{\csname l_siunitx_number_unit_separator_tl\endcsname}}%
    \@ifmtarg{#3}{}{~\SI{#3}{\second}}%
    }%
    }
    \makeatother
    \newcommand{\sep}{\qquad}
    \begin{document}

    $\sitime{10;7;12}-\sitime{9;13;8}$

    \end{document} 

enter image description here

Modified code to use : as a separator for the arguments: use

    \makeatletter
    \newcommand{\sitime}[1]{\sitime@aux#1:::\@nil}
    \def\sitime@aux#1:#2:#3:#4\@nil{%
      \@ifmtarg{#1#2#3}%
      {%
        \PackageError{siunitx (modified)}%
                     {Empty \string\sitime\space argument}{}%
      }%
    {%
    \@ifmtarg{#1}{}{\SI{#1}{\hour}\@ifmtarg{#2#3}{}{\csname l_siunitx_number_unit_separator_tl\endcsname}}%
    \@ifmtarg{#2}{}{\ \SI{#2}{\minute}\@ifmtarg{#3}{}{\csname l_siunitx_number_unit_separator_tl\endcsname}}%
    \@ifmtarg{#3}{}{\ \SI{#3}{\second}}%
    }%
    }
    \makeatother
  • Thank you for your interest in this question. Is it possible to make the separator an option (local or global) so that I can define : or ; or any other symbol as separator? – AndréC Oct 11 at 16:27
  • Do you mean the separator between number and unit components of the duration? – Bernard Oct 11 at 16:33
  • I think of the separator of the macro so that I can choose between \sitime{10:7:12} \sitime{10;7;12} or even \sitime{10,7,12} etc. – AndréC Oct 11 at 16:35
  • It's a minor modification. Please see my addendum for that. B.t.w., does the Lebossé-Hémery series still exist? – Bernard Oct 11 at 16:50
  • They only exist in second-hand. Some of them can be found here: manuelsanciens.blogspot.com/p/maths-college-lycee-prepa.html – AndréC Oct 11 at 16:57

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.