我正在尝试学习 latex3 来编写更强大的 LaTeX 函数。为此,我正在实现一个timesum
包含时间(以分钟为单位)的变量。您可以将小时、天或分钟添加到该总和中。效果很好。
现在我尝试将其输出timesum
分成天、小时和分钟。
但是,甚至没有找到总和中的完整天数,而是中断了Missing number, treated as zero
。
我不懂为什么...
\documentclass{scrlttr2}
\renewcommand\familydefault{\sfdefault}
\usepackage[defaultsans, scale=0.9]{opensans}
\ExplSyntaxOn
\fp_new:N \timesum
\NewDocumentCommand{\addtime}{O{\timesum}mm}
{
\str_case_e:nnF { #3 } {
{h}{\fp_add:Nn #1 {\fp_eval:n {#2 * 60}}}
{d}{\fp_add:Nn #1 {\fp_eval:n {#2 * 60 * 24}}}
}
{ \fp_add:Nn #1 {#2} } % default
#2\,#3
}
\NewDocumentCommand{\showtimesum}{O{\timesum}m}{
\str_case_e:nnF { #2 } {
{h}{\fp_eval:n { #1 / 60}\,h}
{d}{\fp_eval:n {#1 / 60 / 24}\,d}
{min}{\fp_use:N #1 \,min}
}
{ \fp_use:N #1 \,min} % default
}
%\int_incr:N
\NewDocumentCommand{\strtime}{O{\timesum}}{
\fp_new:N \l_fp_tmp_timemin % new var
\fp_set_eq:NN \l_fp_tmp_timemin #1 % set var to value of #1
%\fp_use:N \l_fp_tmp_timemin % print var
% find out days iteratively
\int_do_while:nNnn {\l_fp_tmp_timemin} {>} {1439.999} {
\fp_sub:Nn \l_fp_tmp_timemin {1440}
%\fp_use:N \l_fp_tmp_timemin
}
}
\ExplSyntaxOff
\begin{document}
\begin{letter}{recipient}
\opening{opening}
\addtime{20.5}{h}
\addtime{30}{min}
\addtime{2.7}{d}
\showtimesum{h}
\strtime
%\showsum
\closing{concluding text}
\end{letter}
\end{document}
答案1
您当然可以将时间总和(以分钟为单位)存储在变量中fp
,但是为了打印总时间,您需要将其四舍五入为整数。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\newtime}{m}
{
\fp_new:c { l_mrcarnivore_time_#1_fp }
}
\newtime{default} % initialize one
% \addtime* will also show the added time
\NewDocumentCommand{\addtime}{sO{default}mm}
{
\mrcarnivore_time_add:nnn { #2 } { #3 } { #4 }
% with \addtime* also show what's been added
\IfBooleanT{#1}{#3\,\textup{#4}}
}
\NewDocumentCommand{\strtime}{O{default}}
{
\mrcarnivore_time_str:n { #1 }
}
\int_new:N \l__mrcarnivore_time_days_int
\int_new:N \l__mrcarnivore_time_hours_int
\int_new:N \l__mrcarnivore_time_minutes_int
\cs_new_protected:Nn \mrcarnivore_time_add:nnn
{
\str_case:nnF { #3 }
{
{h}{ \fp_add:cn { l_mrcarnivore_time_#1_fp } { #2 * 60 } }
{d}{ \fp_add:cn { l_mrcarnivore_time_#1_fp } { #2 * 60 * 24 } }
{min}{ \fp_add:cn { l_mrcarnivore_time_#1_fp } { #2 } }
}
{\ERROR}
}
\cs_new_protected:Nn \mrcarnivore_time_str:n
{
% round to an integral number of minutes
\int_set:Nn \l__mrcarnivore_time_minutes_int
{
\fp_eval:n { round( \fp_use:c { l_mrcarnivore_time_#1_fp }, 0 ) }
}
% compute the number of days
\int_set:Nn \l__mrcarnivore_time_days_int
{
\int_div_truncate:nn { \l__mrcarnivore_time_minutes_int } { 1440 }
}
% remove the days
\int_set:Nn \l__mrcarnivore_time_minutes_int
{
\int_mod:nn { \l__mrcarnivore_time_minutes_int } { 1440 }
}
% compute the number of hours
\int_set:Nn \l__mrcarnivore_time_hours_int
{
\int_div_truncate:nn { \l__mrcarnivore_time_minutes_int } { 60 }
}
% remove the hours
\int_set:Nn \l__mrcarnivore_time_minutes_int
{
\int_mod:nn { \l__mrcarnivore_time_minutes_int } { 60 }
}
% now print the days
\int_compare:nT { \l__mrcarnivore_time_days_int > 0 }
{
\int_eval:n { \l__mrcarnivore_time_days_int }\,\textup{d}\;
}
% now print the hours
\int_compare:nTF { \l__mrcarnivore_time_hours_int > 0 }
{
\int_eval:n { \l__mrcarnivore_time_hours_int }\,\textup{h}
}
{% no hours
\unkern
}
\;
% now print the minutes
\int_compare:nTF { \l__mrcarnivore_time_minutes_int > 0 }
{
\int_eval:n { \l__mrcarnivore_time_minutes_int }\,\textup{min}
}
{% no minutes
\unkern
}
}
\ExplSyntaxOff
\begin{document}
\addtime{20.5}{h}
\strtime
\addtime{30}{min}
\strtime
\addtime{2.7}{d}
\strtime
\end{document}
那怎么\unkern
办呢?假设最终答案应该是“两天零八分钟”。
代码将\,
在 2 和 d 之间添加一个细小的空格,并\;
在其后添加一个 med 空格。如果没有小时数可显示,则此 med 空格将保留并与小时数后发出的 med 空格累积。当分钟数为零时也是如此。