L3 相当于 ifcase

L3 相当于 ifcase

考虑仅显示月份和年份的日期的自定义代码:

\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~表示“不间断空格”。

相关内容