考虑仅显示月份和年份的日期的自定义代码:
\def\shccustomdate{%
\ifcase \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\fi,\space
\number\year}
等效解决方案是什么xparse
?
我找到了\if_case:w
原始的但不知道如何使用它。
这是我的尝试:
\NewDocumentCommand{\shccustomdate}{}
{
\if_case:w \int_eval:n { \c_sys_month_int }
\or: January
\or: February
\or: March
\or: April
\or: May
\or: June
\or: July
\or: August
\or: September
\or: October
\or: November
\or: December
\fi: ,~
\int_eval:n { \c_sys_year_int }
}
这是正确实现的吗或者有更好的方法吗?
答案1
是的,您可以像以前一样使用原语\if_case:w
,但更正确的方法是使用\int_case:nn
。这是一个明确区分文档级和代码级接口的实现,以及一些用于更改日期格式的语法糖:
\documentclass{book}
\usepackage{xparse}
\usepackage{nth}
\ExplSyntaxOn
% Document level
\NewDocumentCommand \shccustomdate { } { \shc_date: }
\NewDocumentCommand \shcdateformat { m } { \shc_set_date_format:n {#1} }
\NewExpandableDocumentCommand \monthname { m } { \shc_month_name:n {#1} }
% Code level
\cs_new_protected:Npn \shc_date:
{
\__shc_print_date:xxx
{ \int_use:N \c_sys_day_int }
{ \int_use:N \c_sys_month_int }
{ \int_use:N \c_sys_year_int }
}
\cs_new_protected:Npn \shc_set_date_format:n #1
{ \cs_set_protected:Npn \__shc_print_date:nnn ##1 ##2 ##3 {#1} }
\cs_generate_variant:Nn \__shc_print_date:nnn { xxx }
\cs_new:Npn \shc_month_name:n #1
{
\int_case:nn {#1}
{
{ 1 } { January }
{ 2 } { February }
{ 3 } { March }
{ 4 } { April }
{ 5 } { May }
{ 6 } { June }
{ 7 } { July }
{ 8 } { August }
{ 9 } { September }
{ 10 } { October }
{ 11 } { November }
{ 12 } { December }
}
}
% Default format
\cs_new_protected:Npn \__shc_print_date:nnn #1 #2 #3 { \monthname{#2},~#3 }
\ExplSyntaxOff
\begin{document}
\verb|\shcdateformat{\monthname{#2}, #3}|:
\shccustomdate
\bigskip
\verb|\shcdateformat{\monthname{#2} \nth{#1}, #3}|:
\shcdateformat{\monthname{#2} \nth{#1}, #3}
\shccustomdate
\end{document}
上面的代码分为两部分。第一部分使用 设置日期格式\shc_set_date_format:n
。该函数主要定义:
\cs_new_protected:Npn \__shc_print_date:nnn #1 #2 #3
{ <format> }
其中<format>
是 的参数\shcdateformat
,并且该参数中#1
是日,#2
是月,#3
是年。
然后第二部分,\shc_date:
,扩展\c_sys_day_int
,\c_sys_month_int
(使用将月份进一步扩展为其名称\int_case:nn
)和\c_sys_year_int
,并将它们作为参数传递给\__shc_print_date:nnn
进行排版的。
答案2
我会使用\clist_item:Nn
常量列表。
\documentclass{article}
%\usepackage{xparse} % not needed for LaTeX 2020-10-01 or later
\ExplSyntaxOn
\NewDocumentCommand{\shccustomdate}{O{english}}
{
\azetina_date_monthname:n { #1 }
\azetina_date_separator:n { #1 }
\azetina_year:
}
\clist_const:Nn \c_azetina_date_months_english_clist
{
January,February,March,April,May,June,July,
August,September,October,November,December
}
\tl_const:Nn \c_azetina_date_separator_english_tl { ,\nobreakspace }
\clist_const:Nn \c_azetina_date_months_italian_clist
{
gennaio,febbraio,marzo,aprile,maggio,giugno,luglio,
agosto,settembre,ottobre,novembre,dicembre
}
\clist_const:Nn \c_azetina_date_separator_italian_tl { \nobreakspace }
\cs_new:Nn \azetina_date_monthname:n
{
\clist_item:cn { c_azetina_date_months_#1_clist } { \c_sys_month_int }
}
\cs_new:Nn \azetina_date_separator:n
{
\tl_use:c { c_azetina_date_separator_#1_tl }
}
\cs_new:Nn \azetina_year:
{
\int_to_arabic:n { \c_sys_year_int }
}
\ExplSyntaxOff
\begin{document}
\shccustomdate
\shccustomdate[italian]
\end{document}
如果没有多语言支持,这将归结为
\NewDocumentCommand{\shccustomdate}{}
{
\clist_item:Nn \c_azetina_date_monthname_clist { \c_sys_month_int }
,\nobreakspace
\int_to_arabic:n { \c_sys_year_int }
}
\clist_const:Nn \c_azetina_date_monthname_clist
{
January,February,March,April,May,June,July,
August,September,October,November,December
}
除非用户篡改\c_sys_month_int
,否则这是足够安全的,因为常数将一定计算结果为所需范围 [1–12] 内的整数。
这里支持在运行时选择不同的格式。
\documentclass{article}
%\usepackage{xparse} % not needed for LaTeX 2020-10-01 or later
\usepackage{nth}
\ExplSyntaxOn
\NewDocumentCommand{\shccustomdate}{}
{
\azetina_date_custom:nnn { \c_sys_year_int } { \c_sys_month_int } { \c_sys_day_int }
}
\NewDocumentCommand{\shcsetformat}{m}
{
\cs_set:Nn \azetina_date_custom:nnn { #1 }
}
\NewExpandableDocumentCommand{\decimal}{m}
{
\int_to_arabic:n { #1 }
}
\NewExpandableDocumentCommand{\monthname}{m}
{
\clist_item:Nn \c_azetina_date_monthname_clist { #1 }
}
\clist_const:Nn \c_azetina_date_monthname_clist
{
January,February,March,April,May,June,July,
August,September,October,November,December
}
\ExplSyntaxOff
% initialize
\shcsetformat{\monthname{#2},~\decimal{#1}}
\begin{document}
\shccustomdate
\shcsetformat{\monthname{#2}~\nth{#3}, \decimal{#1}}
\shccustomdate
\end{document}
在 中\shcsetformat
,根据 ISO 惯例#1
,表示年、#2
月、#3
日。请注意,由于格式的设置是在外部进行的\ExplSyntaxOn
-之外\ExplSyntaxOff
,因此 tie~
表示“不间断空格”。