将日期存储在宏中:
\def\Mydate{20-12-2017}
我想使用 进行一些计算(提前几天/几个月)datetime2
。如果\Mydate
以 yyyy-mm-dd 格式存储日期,我不会遇到问题,但如果以不同的格式存储日期(例如 dd-mm-yyyy),命令\DTMsavedate
将无法识别它,我无法发出
\DTMsavedate{testdate}{\MyDate}
我可以使用一些字符串操作将存储在宏中的日期转换为所需的iso
格式\DTMsavedate
,但我希望这种转换由同一个datetime2
包或一个处理指定输入样式的日期字符串的包来完成。在\Mydate
示例中,用户应该以ddmmyyyy
与决定使用“mmddyyyy”格式相同的方式指定格式和分隔符。
是否有某种方法可以输入给定的日期dd-mm-yyyy
来datetime2
进行操作?
如果可以指定输入格式并将日期转换为包识别的格式的任务委托给同一个包,那就更好了。
答案1
\DTMsavedate
您可以像以下代码中一样重新定义:
\documentclass{article}
\usepackage[calc]{datetime2}
\let\DTMsaved=\DTMsavedate
\def\DTMsavedate#1#2{%
\expandafter \ifx \csname f=\DTMinformat\endcsname \relax
\message{! \string\DTMsavedate: input format "\DTMinformat" undeclared}%
\else \csname f=\DTMinformat\expandafter\endcsname#2&{#1}\fi
}
\def\DTMfdef#1{\expandafter\def\csname f=#1\endcsname}
\def\DTMs#1#2{\DTMsaved{#2}{#1}}
\def\DTMinformat{yyyy-mm-dd}
% input format declarations:
\DTMfdef{yyyy-mm-dd}#1-#2-#3&{\DTMs{#1-#2-#3}} % iso input
\DTMfdef{dd-mm-yyyy}#1-#2-#3&{\DTMs{#3-#2-#1}}
\DTMfdef{yyyymmdd}#1#2#3#4#5#6#7#8&{\DTMs{#1#2#3#4-#5#6-#7#8}}
\DTMfdef{ddmmyyyy}#1#2#3#4#5#6#7#8&{\DTMs{#5#6#7#8-#3#4-#1#2}}
\DTMfdef{dd.mm.yyyy}#1.#2.#3&{\DTMs{#3-#2-#1}}
\begin{document}
\def\DTMinformat{yyyy-mm-dd}
\DTMsavedate{test1}{2017-12-20}
\def\DTMinformat{dd-mm-yyyy}
\DTMsavedate{test2}{20-10-2017}
\def\DTMinformat{yyyymmdd}
\DTMsavedate{test3}{20171020}
\def\DTMinformat{dd.mm.yyyy}
\DTMsavedate{test4}{21.5.2017}
Test1 is \DTMusedate{test1}
Test2 is \DTMusedate{test2}
Test3 is \DTMusedate{test3}
Test4 is \DTMusedate{test4}
\end{document}
答案2
用于输入日期的主要日期解析器datetime2
是\@dtm@parsedate
。可以将其重新定义为使用dd-mm-yyyy
输入,所有其他datetime2
命令将像以前一样工作。当然,显示样式无论如何都是由设置的datetime2
。
datetime2
在同一个文档中很容易识别 两种输入样式。
以下是一个例子:
\documentclass{article}
\usepackage[calc]{datetime2}
\newcount\myct
% Make datetime2 use either dd-mm-yyyy input format or iso format
\makeatletter
\@ifpackageloaded{datetime2-calc}
{\def\@dtm@parsedate#1-#2-#3\@dtm@endparsedate{%
\ifnum#1>31\relax
\pgfcalendardatetojulian{#1-#2-#3}{\@dtm@julianday}%
\else
\pgfcalendardatetojulian{#3-#2-#1}{\@dtm@julianday}%
\fi
\pgfcalendarjuliantodate{\@dtm@julianday}{\@dtm@year}{\@dtm@month}{\@dtm@day}%
\pgfcalendarjuliantoweekday{\@dtm@julianday}{\count@}%
\edef\@dtm@dow{\number\count@}%
}}
{\def\@dtm@parsedate#1-#2-#3\@dtm@endparsedate{%
\edef\@dtm@month{\number#2}%
\ifnum#1>31\relax
\edef\@dtm@year{\number#1}%
\edef\@dtm@day{\number#3}%
\else
\edef\@dtm@day{\number#1}%
\edef\@dtm@year{\number#3}%
\fi
\def\@dtm@dow{-1}%
}}
\makeatother
\DTMsetstyle{ddmmyyyy} % Set output format to match
\begin{document}
\DTMsavenow{mynow}
\DTMsavedate{dec20}{20-12-2017}
\DTMsavedate{oct20}{20-10-2017}
\DTMsavedate{oct20iso}{2017-10-20}
Today is \DTMusedate{mynow}
December 20th is \DTMusedate{dec20}
October 20th is \DTMusedate{oct20}
October 20th ISO input is \DTMusedate{oct20iso}
\DTMsaveddatediff{oct20}{dec20}{\myct}
\DTMusedate{oct20} is
\ifnum\myct=0
the same day as
\else
\ifnum\myct<0
\number-\myct\space day\ifnum\myct<-1s\fi\space before
\else
\number\myct\space day\ifnum\myct>1s\fi\space after
\fi \fi
\DTMusedate{dec20}
\end{document}