![datetime2从指定日期中提取年、月、日](https://linux22.com/image/400637/datetime2%E4%BB%8E%E6%8C%87%E5%AE%9A%E6%97%A5%E6%9C%9F%E4%B8%AD%E6%8F%90%E5%8F%96%E5%B9%B4%E3%80%81%E6%9C%88%E3%80%81%E6%97%A5.png)
我制作了一个如下命令:
\newcommand*{\numdash}{\,--\,}
\ExplSyntaxOn
\NewDocumentCommand{\dateRange}{mmmmmm}
{
\str_case:nnF { #1 }
{
{#4} {
\str_case:nnF { #2 }
{
{#5} {
\str_case:nnF { #3 }
{
{#6} { \DTMdisplaydate{#4}{#5}{#6}{-1} }%
}{\DTMordinal{#3}{}{}\numdash{}\DTMdisplaydate{#4}{#5}{#6}{-1}}
}
}{\DTMordinal{#3}~\DTMmonthname{#2}%
{}\numdash{}\DTMdisplaydate{#4}{#5}{#6}{-1}}
}
}{\DTMdisplaydate{#1}{#2}{#3}{-1}{}\numdash{}\DTMdisplaydate{#4}{#5}{#6}{-1}}
}
\ExplSyntaxOff
它以简洁的方式显示从一个日期到下一个日期的持续时间。参见下图。
但是,我需要通过将结束日期增加几天来操纵它。类似的东西\dateRange{2016}{12}{31}{2016}{12}{31 + 1}
不起作用。我发现以下代码
%https://tex.stackexchange.com/questions/318006/add-n-days-to-variable-date
\DTMsavedate{DeadLineDate}{2016-05-20}
\newcommand{\DeadLineDateExtend}{1}
\newcount\daycount
\newcommand{\dueDate}[1]{%
\DTMsaveddateoffsettojulianday{DeadLineDate}{#1}\daycount
\DTMsavejulianday{newDeadLineDate}{\number\daycount}
\DTMusedate{newDeadLineDate}
}
它可以向 a 添加天数DTMdate
。我的问题是让这两个函数一起工作。
- 重写
dateRange
以便输入两个DTMdates
而不是简单的数字。 - 提取年,月和日期并将
newDeadLineDate
其重新插入dateRange
因此我需要的帮助是首先有两个日期,增加其中一个日期并使用\dateRange
函数显示日期范围。如能对上述列表中的 1. 或 2. 提供帮助,我将不胜感激。
\documentclass{article}
\usepackage[english]{babel}
\usepackage[en-GB,calc]{datetime2}
\usepackage{xparse}
% https://tex.stackexchange.com/questions/390693/datetime-ranges-using-datetime2/390738
\newcommand*{\numdash}{\,--\,}
\ExplSyntaxOn
\NewDocumentCommand{\dateRange}{mmmmmm}
{
\str_case:nnF { #1 }
{
{#4} {
\str_case:nnF { #2 }
{
{#5} {
\str_case:nnF { #3 }
{
{#6} { \DTMdisplaydate{#4}{#5}{#6}{-1} }%
}{\DTMordinal{#3}{}{}\numdash{}\DTMdisplaydate{#4}{#5}{#6}{-1}}
}
}{\DTMordinal{#3}~\DTMmonthname{#2}%
{}\numdash{}\DTMdisplaydate{#4}{#5}{#6}{-1}}
}
}{\DTMdisplaydate{#1}{#2}{#3}{-1}{}\numdash{}\DTMdisplaydate{#4}{#5}{#6}{-1}}
}
\ExplSyntaxOff
%https://tex.stackexchange.com/questions/318006/add-n-days-to-variable-date
\DTMsavedate{DeadLineDate}{2016-05-20}
\newcommand{\DeadLineDateExtend}{1}
\newcount\daycount
\newcommand{\dueDate}[1]{%
\DTMsaveddateoffsettojulianday{DeadLineDate}{#1}\daycount
\DTMsavejulianday{newDeadLineDate}{\number\daycount}
\DTMusedate{newDeadLineDate}
}
\begin{document}
\dateRange{2016}{12}{31}{2016}{12}{31}
\dateRange{2016}{12}{30}{2016}{12}{31}
\dateRange{2016}{11}{31}{2016}{12}{31}
\dateRange{2015}{12}{31}{2016}{12}{31}
\end{document}
答案1
datetime2
从指定日期中提取年、月、日
您可能注意到,在代码示例中使用了命令\DTMsavedate
和,该包可以将日期保存在由 〈name〉 标识的特殊存储中。引用部分\DTMsavejulianday
datetime2
存储和使用日期和时间手册内容datetime2
:
在下面的命令中,〈name〉(没有活动字符)是唯一标识信息的名称。
当您在这样的存储中有一个日期时(如执行 后的情况)\DTMsavejulianday{〈name〉}{〈number〉}
,您可以使用命令\DTMfetchyear
、\DTMfetchmonth
和提取相应的年份、月份和日期\DTMfetchday
。这些命令中的每一个都采用 〈name〉 参数并扩展为相应的数字。换句话说,\DTMfetchyear{〈name〉}
扩展到年份、\DTMfetchmonth{〈name〉}
月份和\DTMfetchday{〈name〉}
日期。其余的基本上是管道工作。 :-)
连接不同部分
我建议一个\dateRange
与您的命令行为类似的命令,不同之处在于:
它接受一个可选参数(默认为 0),该参数指定在显示结果范围之前要在结束日期中添加的天数;
它在日期序数和月份名称之间使用不间断空格(在制度
~
下是正常的空格\ExplSyntaxOn
,但我相信你想要一个不间断空格);它使用整数比较,因此对于所有日、月和年参数
01
,被认为与 相同1
,02
与 相同2
,等等(如果您不想要这样,请使用\str_if_eq:nnTF
该答案的第一个修订版中的 ,但我看不出这样做有什么好的理由)。
我重新缩进该函数并使用\int_compare:nNnTF
来\str_case:nnF
使代码更易于阅读并解决上面的第三点。
我还定义了一个代码级函数\nebuch_display_date_range:nnnnnn
来包含这个重新编写的代码,因为这样在不同情况下重用起来更容易。这使我们能够生成一个变体\nebuch_display_date_range:nnnxxx
,在将最后三个参数传递给基函数之前,先将其完全展开\nebuch_display_date_range:nnnnnn
(完全展开由 完成\edef
)。这只需要一行简单的代码:
\cs_generate_variant:Nn \nebuch_display_date_range:nnnnnn { nnnxxx }
使用变体,很容易将临时日期计算的结果(添加了偏移量)传递给基函数\nebuch_display_date_range:nnnnnn
,因为\DTMfetchday
、\DTMfetchmonth
和\DTMfetchyear
都是可扩展函数(参见的文档datetime2
)。
偏移日期的计算也是在代码级函数中实现的,即\nebuch_compute_offset_date:nnnnn
,以便其他代码可以轻松地重用它(并且它在我的实现中使用\dateRange
)。
\documentclass{article}
\usepackage[english]{babel}
\usepackage[en-GB,calc]{datetime2}
\usepackage{xparse}
\newcommand*{\numdash}{\,--\,}
\ExplSyntaxOn
% Similar to your \dateRange, but we use integer comparisons here and the
% code-level API allows the creation of variants with \cs_generate_variant:Nn.
\cs_new_protected:Npn \nebuch_display_date_range:nnnnnn #1#2#3#4#5#6
{
\int_compare:nNnTF {#1} = {#4}
{
\int_compare:nNnTF {#2} = {#5}
{
\int_compare:nNnTF {#3} = {#6}
{ \DTMdisplaydate {#4} {#5} {#6} {-1} }
{
\DTMordinal {#3} {} {} \numdash
\DTMdisplaydate {#4} {#5} {#6} {-1}
}
}
{
% I replaced ~ with \nobreakspace here because of \ExplSyntaxOn
\DTMordinal {#3} \nobreakspace \DTMmonthname {#2} \numdash
\DTMdisplaydate {#4} {#5} {#6} {-1}
}
}
{
\DTMdisplaydate {#1} {#2} {#3} {-1} \numdash
\DTMdisplaydate {#4} {#5} {#6} {-1}
}
}
\cs_generate_variant:Nn \nebuch_display_date_range:nnnnnn { nnnxxx }
\newcount \nebuch_tmp_count
% #1, #2, #3: year, month, day
% #4: number of days (offset)
% #5: <name> (in the sense of datetime2) used to store the resulting date
\cs_new_protected:Npn \nebuch_compute_offset_date:nnnnn #1#2#3#4#5
{
\DTMsavedate { nebuch_compute_offset_date_tmp_date } { #1-#2-#3 }
\DTMsaveddateoffsettojulianday
{ nebuch_compute_offset_date_tmp_date } {#4} { \nebuch_tmp_count }
\DTMsavejulianday {#5} { \number \nebuch_tmp_count }
}
\NewDocumentCommand { \dateRange } { O{0} m m m m m m }
{
\nebuch_compute_offset_date:nnnnn {#5} {#6} {#7} {#1}
{ nebuch_dateRange_tmp_date }
\nebuch_display_date_range:nnnxxx {#2} {#3} {#4}
{ \DTMfetchyear { nebuch_dateRange_tmp_date } }
{ \DTMfetchmonth { nebuch_dateRange_tmp_date } }
{ \DTMfetchday { nebuch_dateRange_tmp_date } }
}
\ExplSyntaxOff
\begin{document}
\dateRange{2016}{12}{31}{2016}{12}{31}\par
\dateRange{2016}{12}{30}{2016}{12}{31}\par
\dateRange{2016}{11}{31}{2016}{12}{31}\par
\dateRange{2015}{12}{31}{2016}{12}{31}
\bigskip
\dateRange[3]{2016}{12}{31}{2016}{12}{31}\par
\dateRange[3]{2016}{12}{31}{2016}{12}{28}\par
\dateRange[3]{2016}{12}{30}{2016}{12}{31}\par
\dateRange[3]{2016}{12}{30}{2016}{12}{28}\par
\dateRange[31]{2016}{11}{31}{2016}{12}{31}\par
\dateRange[31]{2016}{11}{31}{2016}{11}{30}\par
\dateRange[365]{2015}{12}{31}{2016}{12}{31}\par
\dateRange[365]{2015}{12}{31}{2016}{01}{01}
\bigskip
\dateRange{2016}{02}{7}{2016}{2}{07}
\end{document}