使用 `datetime2` 的日期(时间)范围

使用 `datetime2` 的日期(时间)范围

我想使用datetime2用于格式化日期(时间)范围的包。

例如,\DTMdaterange{2017-08-05}{2017-09-10}将以2017-08-05/09-10ISO 格式输出,或者以类似August 5 to September 10, 2017美国英语的格式输出。

我考虑过自己实现它,但发现有点难。除了isodate? 我想biblatex可能是一个很好的候选人,但找不到任何有用的东西(我最感兴趣的是格式化日期;时间不是必需的)。

答案1

我不知道datetime2包可以做,但我很好奇你能用什么来做鍵盤以统一的方式格式化日期。

这提供了一些用于输入日期的代码和调整显示日期格式的统一方法。\DateRange我认为还有一个方法,它以依赖于当前“日期格式”的方式执行您想要的操作。

下面的代码产生:

在此处输入图片描述

最后两行是具有不同格式的“日期范围”。

代码如下:

\documentclass{article}
\usepackage{pgfkeys}
\usepackage{pgfmath}% for calculating yy from yyyy
\usepackage{siunitx}% we use the \num command for dd and mm format in the

\newif\ifPrintYear\PrintYeartrue%   controls if year  is printed
\newif\ifPrintMonth\PrintMonthtrue% controls if month is printed

\pgfkeys{/mydate/.is family, /mydate,
  year/.initial=0,
  month/.initial=0,
  day/.initial=0,
  date format/.initial = dmyy,
  date range separator/.initial = {-},% used to separate dates in \DateRange
  format day d/.code = {\pgfkeysvalueof{/mydate/day}}, % format ways to the day
  format day dd/.code = {\num[minimum-integer-digits=2]{\pgfkeysvalueof{/mydate/day}}},
  format month/.code n args={3}{%  <format month><pre-text><post-text>
    \ifPrintMonth#2\pgfkeys{/mydate/format month #1}#3\fi%
  },
  format month m/.code = {\pgfkeysvalueof{/mydate/month}},
  format month mm/.code = {\num[minimum-integer-digits=2]{\pgfkeysvalueof{/mydate/month}}},
  format month mmm/.code={%
    \expandafter\ifcase\pgfkeysvalueof{/mydate/month}??%
    \or Jan%
    \or Feb%
    \or Mar%
    \or Apr%
    \or May%
    \or Jun%
    \or Jul%
    \or Aug%
    \or Sep%
    \or Oct%
    \or Nov%
    \or Dec%
    \else ???%
    \fi%
  },
  format month mmmm/.code={%
    \expandafter\ifcase\pgfkeysvalueof{/mydate/month}??%
    \or January%
    \or February%
    \or March%
    \or April%
    \or May%
    \or June%
    \or July%
    \or August%
    \or September%
    \or October%
    \or November%
    \or December%
    \else ???%
    \fi%
  },
  format year/.code n args={3}{% <format year><pre-text><post-text>
    \ifPrintYear#2\pgfkeys{/mydate/format year #1}#3\fi%
  },
  format year yy/.code = {%
      \pgfmathparse{Mod(\pgfkeysvalueof{/mydate/year},100)}%
      \num[minimum-integer-digits=2,zero-decimal-to-integer]{\pgfmathresult}%
  },
  format year yyyy/.code = {%
      \pgfkeysvalueof{/mydate/year}%
  },
  output/dmyy/.code = {%
    \pgfkeys{/mydate/format day d}%
    \pgfkeys{/mydate/format month={m}{/}{\relax}}%
    \pgfkeys{/mydate/format year={yy}{/}{\relax}}%
    \pgfkeyssetvalue{/mydate/date range separator}{ to }%
  },
  output/dmyyyy/.code = {%
    \pgfkeys{/mydate/format day d}%
    \pgfkeys{/mydate/format month={m}{/}{\relax}}%
    \pgfkeys{/mydate/format year={yyyy}{/}{\relax}}%
    \pgfkeyssetvalue{/mydate/date range separator}{ to }%
  },
  output/ddmmyy/.code = {%
    \pgfkeys{/mydate/format day dd}%
    \pgfkeys{/mydate/format month={mm}{/}{\relax}}%
    \pgfkeys{/mydate/format year={yy}{/}{\relax}}%
    \pgfkeyssetvalue{/mydate/date range separator}{ to }%
  },
  output/ddmmyyyy/.code = {%
    \pgfkeys{/mydate/format day dd}%
    \pgfkeys{/mydate/format month={mm}{/}{\relax}}%
    \pgfkeys{/mydate/format year={yyyy}{/}{\relax}}%
    \pgfkeyssetvalue{/mydate/date range separator}{ to }%
  },
  output/mmmdyyyy/.code = {%
    \pgfkeys{/mydate/format month={mmm}{\relax}{ }}%
    \pgfkeys{/mydate/format day d}%
    \pgfkeys{/mydate/format year={yyyy}{, }{\relax}}%
    \pgfkeyssetvalue{/mydate/date range separator}{ to }%
  },
  output/mmmmdyyyy/.code = {%
    \pgfkeys{/mydate/format month={mmmm}{\relax}{ }} %
    \pgfkeys{/mydate/format day d}%
    \pgfkeys{/mydate/format year={yyyy}{ }{\relax}}%
    \pgfkeyssetvalue{/mydate/date range separator}{ to }%
  },
  output/yyyymd/.code = {%
    \pgfkeys{/mydate/format year={yyyy}{\relax}{/}}%
    \pgfkeys{/mydate/format month={m}{\relax}{/}}%
    \pgfkeys{/mydate/format day d}%
    \pgfkeyssetvalue{/mydate/date range separator}{ to }%
  },
  output/yyyymmdd/.code = {%
    \pgfkeys{/mydate/format year={yyyy}{\relax}{/}}%
    \pgfkeys{/mydate/format month={mm}{\relax}{/}}%
    \pgfkeys{/mydate/format day dd}%
    \pgfkeyssetvalue{/mydate/date range separator}{ to }%
  },
  output/iso/.code = {%
    \pgfkeys{/mydate/format year={yyyy}{\relax}{-}}%
    \pgfkeys{/mydate/format month={mm}{\relax}{-}}%
    \pgfkeys{/mydate/format day dd}%
    \pgfkeyssetvalue{/mydate/date range separator}{/}%
  },
  printdate/.code={\pgfkeys{/mydate/output/\pgfkeysvalueof{/mydate/date format}}}
}

% format date input yyyy-m-d ---- but allow yy-m-d
\pgfkeysdefargs{/mydate/date}{#1-#2-#3}{%
   \ifnum#1<100\relax \pgfkeyssetvalue{/mydate/year}{20#1}% assume year is 20XX
   \else\pgfkeyssetvalue{/mydate/year}{#1}%
   \fi%
   \pgfkeyssetvalue{/mydate/month}{#2}%
   \pgfkeyssetvalue{/mydate/day}{#3}%
}

\newcommand\DateFormat[1]{\pgfkeys{/mydate/date format=#1}}
\newcommand\Date[1]{\pgfkeys{/mydate, date=#1, printdate}}

\newcommand\DateRange[2]{%
  \bgroup% start a group so that PrintYear and PrintMonth changes are local
    \Date{#1}%
    \xdef\lastYear{\pgfkeysvalueof{/mydate/year}}%
    \xdef\lastMonth{\pgfkeysvalueof{/mydate/month}}%
    \pgfkeys{/mydate/date=#2}%
    \xdef\thisYear{\pgfkeysvalueof{/mydate/year}}%
    \xdef\thisMonth{\pgfkeysvalueof{/mydate/month}}%
    \ifnum\thisYear=\lastYear\relax%
       \PrintYearfalse%
       \ifnum\thisMonth=\lastMonth\relax%
         \PrintMonthfalse%
       \fi
     \fi%
    \pgfkeysvalueof{/mydate/date range separator}%
    \pgfkeys{/mydate/printdate}%
  \egroup
}

\begin{document}


\Date{2017-08-28}

\DateFormat{ddmmyy}\Date{2017-08-09}

\DateFormat{iso}\Date{2017-08-09}

\DateFormat{mmmdyyyy}\Date{2017-08-09}

\DateFormat{mmmmdyyyy}\Date{2017-08-09}

\DateFormat{iso}
\DateRange{2017-08-05}{2017-08-10}

\DateRange{2017-08-05}{2017-09-10}

\DateRange{2017-08-05}{2018-09-10}

\DateFormat{mmmdyyyy}
\DateRange{2017-08-05}{2017-08-10}

\DateRange{2017-08-05}{2017-09-10}

\DateRange{2017-08-05}{2018-09-10}

\end{document}

代码的思路是yyyy-m-d使用以格式输入日期\Date。可以随时使用 更改日期格式\DateFormat。在后台,存在一些 pgfkeys 技巧,在实际完成打印时调用特定的日期格式。支持的格式都是该/mydate/output键的所有子键,反过来,这些子键又调用各种年、月和日格式键。

为满足日期范围,还有一个额外的复杂因素:年份格式,直到/mydate/format year,都用于\ifPrintYear查看是否应打印年份,为了使它工作,年份格式都接受两个参数,即年份前后的文本,因为当不打印年份时也需要删除它们。同样,月份使用\ifPrintMonth\DateRange检查日期范围内的两个年份,如果它们是相等的集合\PrintYearfalse,结果第二个日期的年份不会被打印。

答案2

datetime2-sample-journal.tex下载中包含的示例文档datetime2有一个如何创建日期范围命令的示例。为了完整起见,下面粘贴了代码(不是我自己的)。

\usepackage[en-GB]{datetime2}

\newcommand*{\numdash}{\texorpdfstring{\,--\,}{--}}

% A range of dates.
% Syntax: \daterange{yyyy1}{mm1}{dd1}{yyyy2}{mm2}{dd2}
\newcommand*{\daterange}[6]{%
  \ifnum#1=#4
% Same year
    \ifnum#2=#5
% Same month
      \ifnum#3=#6
% Same day - not a range!
       \DTMdisplaydate{#1}{#2}{#3}%
      \else
% Range within the same month.
% This needs to be done explicitly but match the separators
% with the en-US style.
       \DTMenglishordinal{#3}\numdash\DTMenglishordinal{#6}%
       \DTMenGBdaymonthsep
       \DTMenglishmonthname{#2}%
       \DTMenGBmonthyearsep\number#1
      \fi
    \else
% Not the same month
      \DTMdisplaydate{#1}{#2}{#3}{-1}\numdash\DTMdisplaydate{#4}{#5}{#6}{-1}%
    \fi
  \else
% Not same year
   \DTMdisplaydate{#1}{#2}{#3}{-1}\numdash\DTMdisplaydate{#4}{#5}{#6}{-1}%
  \fi
}

然后可以用作:

\daterange{2016}{02}{04}{2016}{03}{01}\\
\daterange{2019}{01}{01}{2019}{01}{20}\\
\daterange{2017}{03}{04}{2018}{04}{01}\\

显示:

February 2016 – March 2016
1st – 20th January 2019
March 2017 – April 2018

相关内容