% \iffalse meta-comment % !TEX program = XeLaTeX %<*internal> \iffalse % %<*readme> zhnumber ======== The `zhnumber` package provides commands to typeset Chinese representations of numbers. The main difference between this package and `CJKnumb` is that commands provided by this package is expandable in the proper way. So, it seems that zhnumber is a good alternative to `CJKnumb` package. Basic Usage ----------- The package provides the following macros: \zhnumber{} Convert `` to a full Chinese representation. \zhnum{} Similar to `\arabic{}`, but representation of `` as Chinese numerals. \zhdigits{} \zhdigits*{} Handle `` as a string of digits and convert each of them into the corresponding Chinese digit. The starred version uses the Chinese circle glyph for digit zero; the unstarred version uses the traditional glyph. You can read the package manual (in Chinese) for more detailed explanations. Contributing ------------ This package is a part of the [ctex-kit](https://github.com/CTeX-org/ctex-kit) project. Issues and pull requests are welcome. Copyright and Licence --------------------- Copyright (C) 2012, 2014-2020, 2022 by Qing Lee ---------------------------------------------------------------------- This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. This version of this license is in http://www.latex-project.org/lppl/lppl-1-3c.txt and the latest version of this license is in http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. This work has the LPPL maintenance status "maintained". The Current Maintainer of this work is Qing Lee. This package consists of the file zhnumber.dtx, and the derived files zhnumber.pdf, zhnumber.sty, zhnumber-utf8.cfg, zhnumber-gbk.cfg, zhnumber-big5.cfg, zhnumber.ins and README.md (this file). % %<*internal> \fi \begingroup \def\temp{LaTeX2e} \expandafter\endgroup\ifx\temp\fmtname\else \csname fi\endcsname % %<*install> \input ctxdocstrip % \preamble Copyright (C) 2012, 2014-2020, 2022 by Qing Lee -------------------------------------------------------------------------- This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. This version of this license is in http://www.latex-project.org/lppl/lppl-1-3c.txt and the latest version of this license is in http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. This work has the LPPL maintenance status "maintained". The Current Maintainer of this work is Qing Lee. -------------------------------------------------------------------------- \endpreamble \postamble This package consists of the file zhnumber.dtx, and the derived files zhnumber.pdf, zhnumber.sty, zhnumber-utf8.cfg, zhnumber-gbk.cfg, zhnumber-big5.cfg, zhnumber.ins and README.md. \endpostamble \generate { % %<*internal> \usedir{source/latex/zhnumber} \file{zhnumber.ins} {\from{\jobname.dtx}{install}} % %<*install> \usedir{tex/latex/zhnumber} \file{zhnumber.sty} {\from{\jobname.dtx}{package}} \usedir{tex/latex/zhnumber/config} \file{zhnumber-utf8.cfg} {\from{\jobname.dtx}{config,utf8}} \ctxfile{Big5}{zhnumber-big5.cfg} {\from{\jobname.dtx}{config,big5}} \ctxfile{GBK}{zhnumber-gbk.cfg} {\from{\jobname.dtx}{config,gbk}} \nopreamble\nopostamble \usedir{doc/latex/zhnumber} \file{README.md} {\from{\jobname.dtx}{readme}} } \endbatchfile % %<*internal> \fi % %\NeedsTeXFormat{LaTeX2e} %\RequirePackage{expl3} %<+package|config>\GetIdInfo$Id: zhnumber.dtx 5e8c3fe 2022-07-14 18:53:36 +0800 Qing Lee $ % {Typesetting numbers with Chinese glyphs} % {Chinese numerals with UTF8 encoding} % {Chinese numerals with Big5 encoding} % {Chinese numerals with GBK encoding} %\ProvidesExplPackage{\ExplFileName} %\ProvidesExplFile{\ExplFileName-utf8.cfg} %\ProvidesExplFile{\ExplFileName-big5.cfg} %\ProvidesExplFile{\ExplFileName-gbk.cfg} % {\ExplFileDate}{3.0}{\ExplFileDescription} %<*driver> \documentclass{ctxdoc} \SideBySideExampleSet{xrightmargin=.6\linewidth} \begin{document} \DocInput{\jobname.dtx} \IndexLayout \PrintIndex \end{document} % % \fi % % \CheckSum{1394} % \GetFileId{zhnumber.sty} % % \title{\bfseries\pkg{zhnumber} 宏包} % \author{李清\\ \path{sobenlee@gmail.com}} % \date{\filedate\qquad\fileversion\thanks{\ctexkitrev{\ExplFileVersion}.}} % \maketitle % % \begin{documentation} % % \section{简介} % \pkg{zhnumber} 宏包用于将阿拉伯数字按照中文格式输出。相比于 \pkg{CJKnumb},它提供 % 的四个格式转换命令 \tn{zhnumber},\tn{zhdigits}、\tn{zhnum} 和 \tn{zhdig} % 都是可以适当展开的,可以正常使用于 |PDF| 书签和交叉引用。 % % \pkg{zhnumber} 支持 |GBK|,|Big5| 和 |UTF8| 编码,依赖 \LaTeXiii{} 项目的 % \pkg{expl3},\pkg{xparse} 和 \pkg{l3keys2e} 宏包。 % % \section{使用方法} % % \begin{function}[updated=2022-07-10]{encoding} % \begin{syntax} % encoding = % \end{syntax} % 用于指定编码的宏包选项,可以在调用宏包的时候设定,也可以用 \tn{zhnumsetup} % 在导言区内设定。对于 \upLaTeX、\XeLaTeX{} 和 \LuaLaTeX,不用指定编码,宏包将 % 自动使用 |UTF8| 编码。只有 \LaTeX{} 和 \pdfLaTeX{} 需要指定编码,如果没有指定, % 默认也使用 |UTF8|。 % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhnumber} % \begin{syntax} % \tn{zhnumber} \Arg{number} % \end{syntax} % 以中文格式输出数字。这里的数字可以是整数、小数和分数。例如 % \begin{SideBySideExample} % \zhnumber{2012020120}\\ % \zhnumber{2 012 020 120}\\ % \zhnumber{2,012,020,120}\\ % \zhnumber{2012.020120}\\ % \zhnumber{2012.}\\ % \zhnumber{.2012}\\ % \zhnumber{20120/20120}\\ % \zhnumber{/2012}\\ % \zhnumber{2012/}\\ % \zhnumber{201;2020/120} % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhdigits} % \begin{syntax} % \tn{zhdigits} \Arg{number} % \tn{zhdigits} * \Arg{number} % \end{syntax} % 将阿拉伯数字转换为中文数字串。缺省状态下,\tn{zhdigits} 将 0 映射为〇,如果需要 % 将其映射为零,可以使用带星号的形式。例如 % \begin{SideBySideExample} % \zhdigits{2012020120}\\ % \zhdigits*{2012020120} % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhnum} % \begin{syntax} % \tn{zhnum} \Arg{counter} % \tn{pagenumbering} \{zhnum\} % \end{syntax} % 与 |\roman| 等类似,用于将 \LaTeX 计数器的值转换为中文数字。例如 % \begin{SideBySideExample} % \zhnum{section} % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhdig} % \begin{syntax} % \tn{zhdig} \Arg{counter} % \tn{pagenumbering} \{zhdig\} % \end{syntax} % 与 |\roman| 等类似,用于将 \LaTeX 计数器的值转换为中文数字串。例如 % \begin{SideBySideExample} % \zhdig{section} % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhweekday} % \begin{syntax} % \tn{zhweekday} \Arg{yyyy/mm/dd} % \end{syntax} % 输出日期当天的星期。例如 % \begin{SideBySideExample} % \zhweekday{2012/5/20} % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhdate} % \begin{syntax} % \tn{zhdate} \Arg{yyyy/mm/dd} % \tn{zhdate} * \Arg{yyyy/mm/dd} % \end{syntax} % 以中文格式输出日期,其中带 |*| 的命令还输出星期。例如 % \begin{SideBySideExample} % \zhdate{2012/5/21}\\ % \zhdate*{2012/5/21} % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhtoday} % 与 |\today| 类似,以中文输出当天的日期。例如 % \begin{SideBySideExample} % \zhtoday % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhtime} % \begin{syntax} % \tn{zhtime} \Arg{hh:mm} % \end{syntax} % 以中文格式输出时间。例如 % \begin{SideBySideExample} % \zhtime{23:56} % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhcurrtime} % 输出当前的时间。例如 % \begin{SideBySideExample} % \zhcurrtime % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhtiangan} % \begin{syntax} % \tn{zhtiangan} \Arg{number} % \end{syntax} % 输出对应的天干计数。\meta{number} 的正常范围是 1--10,超出范围的数字将输出空值。例如 % \begin{SideBySideExample}[xrightmargin=.4\linewidth] % \zhtiangan{1} \zhtiangan{2} \zhtiangan{3} % \zhtiangan{4} \zhtiangan{5} \zhtiangan{10} % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhdizhi} % \begin{syntax} % \tn{zhdizhi} \Arg{number} % \end{syntax} % 输出对应的地支计数。\meta{number} 的正常范围是 1--12,超出范围的数字将输出空值。例如 % \begin{SideBySideExample}[xrightmargin=.4\linewidth] % \zhdizhi{1} \zhdizhi{2} \zhdizhi{3} % \zhdizhi{4} \zhdizhi{5} \zhdizhi{12} % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhganzhi} % \begin{syntax} % \tn{zhganzhi} \Arg{number} % \end{syntax} % 输出对应的干支计数。\meta{number} 的正常范围是 1--60,超出范围的数字将输出空值。例如 % \begin{SideBySideExample}[xrightmargin=.4\linewidth] % \zhganzhi{1} \zhganzhi{2} \zhganzhi{3} \\ % \zhganzhi{4} \zhganzhi{5} \zhganzhi{60} % \end{SideBySideExample} % \end{function} % % \begin{function}[EXP, updated=2022-07-10]{\zhganzhinian} % \begin{syntax} % \tn{zhganzhinian} \Arg{year} % \end{syntax} % 输出公元纪年 \meta{year} 对应的干支纪年。公元前的年份用负数表示。例如 % \begin{SideBySideExample}[xrightmargin=.4\linewidth] % \zhganzhinian{1898} \zhganzhinian{-246} \\ % \zhganzhinian{-2697} \zhganzhinian{\year} % \end{SideBySideExample} % \end{function} % % \begin{function}[added=2012-05-25]{\zhnumExtendScaleMap} % \begin{syntax} % \tn{zhnumExtendScaleMap} \oarg{character} \{, , ..., \} % \end{syntax} % 缺省状态下 \tn{zhnumber} 能正确中文格式化的最大整数是 $10^{48}-1$,\tn{zhdigits} 不受 % 这个大小的限制。可以通过 \tn{zhnumExtendScaleMap} 来扩展 \tn{zhnumber}。 % \meta{character_i} 设置 $10^{4(i+11)}$。若给出可选项 \meta{character},则当 % 数字大于 $10^{4(n+12)}-1$ 时,统一用 \meta{character} 设置输出数字的进位。 % \end{function} % % \begin{function}[updated=2022-07-10]{\zhnumsetup} % \begin{syntax} % \tn{zhnumsetup} \{=, =, ...\} % \end{syntax} % 用于在导言区或文档中,设置中文数字的输出格式。目前可以设置的 \meta{key} 如下介绍。 % 以\textbf{粗体}表示选项的默认值。 % \end{function} % % \begin{function}[added=2012-05-25]{time} % \begin{syntax} % time = <(Arabic)|Chinese> % \end{syntax} % 设置日期和时间的数字格式,\meta{Arabic} 为阿拉伯数字,而 \meta{Chinese} 为中文数字。 % 例如 % \begin{SideBySideExample} % \zhnumsetup{time=Chinese} % \zhtoday\zhcurrtime % \end{SideBySideExample} % \end{function} % % \begin{function}[added=2016-05-01]{arabicsep} % \begin{syntax} % arabicsep = \Arg{sep} % \end{syntax} % 设置日期和时间的数字格式为阿拉伯数字时,阿拉伯数字与汉字的间隔内容。默认为一个空格。 % \end{function} % % \begin{function}[updated=2012-05-25]{style} % \begin{syntax} % style = <(Simplified)|Traditional|(Normal)|Financial|Ancient> % \end{syntax} % 意义分别为 % % \begin{description}[font=\mdseries\ttfamily\small,align=right,leftmargin=*, % labelsep=\marginparsep,labelindent=-\marginparsep] % \item[Simplified] 以简体中文输出数字(对 |Big5| 编码无效); % \item[Traditional] 以繁体中文输出数字(对 |Big5| 编码无效); % \item[Normal] 以小写形式输出中文数字; % \item[Financial] 以大写形式输出中文数字; % \item[Ancient] 以廿输出 20,以卅输出 30,以卌输出 40,以皕输出 200。 % \end{description} % % 可以设置 |style| 为其中一个,也可以是前两个与后三个的适当组合,默认是简体小写。例如 % \begin{SideBySideExample}[xrightmargin=.4\linewidth] % \zhnumsetup{style={Traditional,Financial}} % \zhnumber{62012.3}\\ % \zhnumsetup{style=Ancient} % \zhnumber{21} % \end{SideBySideExample} % \end{function} % % \begin{function}{null} % \begin{syntax} % null = <\TFF> % \end{syntax} % 缺省状态下,除了 \tn{zhdigits} 外,其他的格式转换命令,将 0 映射成零,如果需要将 0 映射 % 成〇,可以使用这个选项。 % \end{function} % % \begin{function}[added=2015-05-20]{ganzhi-cyclic} % \begin{syntax} % ganzhi-cyclic = <\TFF> % \end{syntax} % 天干、地支和干支的数字都有一定范围。若参数大于这个范围,\tn{tiangan} 等将输出空值。 % 可以将本选项设置为 |true|,对超出范围的数字取相应的模。 % 请注意,数字 |0| 的结果总是为空值。例如 % \begin{SideBySideExample}[xrightmargin=.3\linewidth] % \zhnumsetup{ganzhi-cyclic} % \zhtiangan{11} \zhtiangan{12} \zhtiangan{209} % \zhtiangan{-1} \zhtiangan{-2} \zhtiangan{-683} \\ % \zhdizhi{13} \zhdizhi{24} \zhdizhi{1211} % \zhdizhi{-1} \zhdizhi{-2} \zhdizhi{-8199} \\ % \zhganzhi{61} \zhganzhi{72} \zhganzhi{2158} \\ % \zhganzhi{-1} \zhganzhi{-2} \zhganzhi{-789} % \end{SideBySideExample} % \end{function} % % \pkg{zhnumber} 提供下列选项来控制阿拉伯数字的中文映射。 % \begin{frameverb} % - -0 0 1 2 3 4 5 6 7 8 9 10 20 30 40 100 200 1000 % E2 E3 E4 E8 E12 E16 E20 E24 E28 E32 E36 E40 E44 % F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F100 F1000 FE2 FE3 % T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 % D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 % GZ1 GZ2 GZ3 GZ4 GZ5 GZ6 GZ7 GZ8 GZ9 GZ10 ... GZ60 % dot and parts % year month day hour minute weekday mon tue wed thu fri sat sun % \end{frameverb} % 其中 |-| 设置负,|-0| 设置〇,|dot| 设置小数的点,|and| 和 |parts| 分别设置分数 % 的“又”和“分之”,|E|$n$ 设置 $10^n$,|F|$n$ 设置数字 $n$ 的大写,|T|$n$ 设置 % 数字 $n$ 的天干,|D|$n$ 设置数字 $n$ 的地支,而 |GZ|$n$ 设置数字 $n$ 的干支。 % 其他的选项同字面意思,不再赘述。例如 % \begin{frameverb} % \zhnumsetup{2={两}} % \end{frameverb} % 可以将 2 映射成两。需要说明的是,\pkg{zhnumber} 将优先使用这里的设置,所以可能会影响 % 到 |style| 选项。如果要恢复 |style| 的功能,可以使用 |reset| 选项。 % % \begin{function}[updated=2022-07-10]{reset} % \begin{syntax} % reset % \end{syntax} % 用于恢复 \pkg{zhnumber} 对阿拉伯数字的初始化映射。\pkg{zhnumber} 的中文数字初始化 % 设置见源代码(第 \ref{sec:zhnum-map} 节)。 % \end{function} % % \begin{function}[added=2014-09-09]{activechar} % \begin{syntax} % activechar = <\TTF> % \end{syntax} % 在 \LaTeX{} 或者 \pdfLaTeX{} 下面输出汉字,传统的办法需要将汉字的首字节设置为 % 活动字符,然后再通过特殊的宏技巧来实现。因此,\pkg{zhnumber} 在载入配置文件的 % 时候,默认会将汉字的首字节设置为活动字符。禁用本选项将不会改变汉字首字节的 % 类代码。需要在本选项之后,使用 \texttt{encoding} 或者 \texttt{reset} 选项 % 才会有效果。 % \end{function} % % \begin{function}[updated=2022-07-10]{\zhnumber,\zhdigits,\zhnum,\zhdig} % \begin{syntax} % \tn{zhnumber} \oarg{options} \Arg{number} % \tn{zhdigits} * \oarg{options} \Arg{number} % \tn{zhnum} \oarg{options} \Arg{counter} % \tn{zhdig} \oarg{options} \Arg{counter} % \end{syntax} % 如果只改变当前数字的中文输出格式,可以使用带选项的格式转换命令,其中 \meta{options} % 与 \tn{zhnumsetup} 的参数相同,如上所介绍。这些带了选项的命令是不可展开的,在某些场合使 % 用时要小心。 % \end{function} % % \end{documentation} % % \StopEventually{} % % \begin{implementation} % % \section{\pkg{zhnumber} 宏包代码实现} % % \begin{macrocode} %<*package> % \end{macrocode} % % \begin{macrocode} %<@@=zhnum> % \end{macrocode} % % \begin{macrocode} \msg_new:nnn { zhnumber } { l3-too-old } { Support~package~'expl3'~too~old. \\\\ Please~update~an~up~to~date~version~of~the~bundles\\\\ 'l3kernel'~and~'l3packages'\\\\ using~your~TeX~package~manager~or~from~CTAN. } \@ifpackagelater { expl3 } { 2019/03/05 } { } { \msg_error:nn { zhnumber } { l3-too-old } } % \end{macrocode} % % \begin{macrocode} \cs_if_exist:NF \NewDocumentCommand { \RequirePackage { xparse } } % \end{macrocode} % % \begin{macro}{\zhnum_output:n,\zhnum_expand_wrap:wn} % 受益于 \tn{tex_expanded:D},我们使用如下的结构简单实现 |f| 展开。 % \begin{verbatim} % \exp_not:e % { % ... % \exp_not:o { } % ... % \exp_not:o { } % ... % \exp_not:o { } % ... % } % \end{verbatim} % 并且可以将 \tn{zhnumber} 等无风险地使用于诸如 \tn{edef} 定义等完全展开的场合。 % 从 \TeXLive\ 2019 开始,各个主要引擎都已经支持 \tn{tex_expanded:D}, % 对于较早的版本,\LaTeXiii\ 也实现了一个模拟。 % \begin{macrocode} \cs_new:Npn \zhnum_output:n #1 { \exp_args:Nc \zhnum_exp_not:o { l_@@_ #1 _tl } } \cs_new_protected:Npn \zhnum_expand_wrap:wn #1# { \@@_expand_wrap_aux:nn {#1} } \cs_new_protected:Npn \@@_expand_wrap_aux:nn #1#2 { #1 { \exp_not:e {#2} } } \cs_new_eq:NN \zhnum_exp_not:e \exp_not:e \cs_new_eq:NN \zhnum_exp_not:o \exp_not:o % \end{macrocode} % 但这种方式也有一定的缺点,比如在 \pdfTeX\ 引擎下,\pkg{hyperref} 包的 % \tn{pdfstringdef} 就需要把汉字首字节的活动字符展开, % 并作适当的重定义后才能得到预期的结果。为此,我们定义一个清除命令,不使用以上机制。 % \begin{macrocode} \cs_new_protected:Npn \zhnumClearWrapper { \cs_set_eq:NN \zhnum_exp_not:e \use:n \cs_set_eq:NN \zhnum_exp_not:o \use:n } \cs_new_protected:Npn \zhnumResetWrapper { \cs_set_eq:NN \zhnum_exp_not:e \exp_not:e \cs_set_eq:NN \zhnum_exp_not:o \exp_not:o } \hook_gput_code:nnn { package/CJKutf8/after } { zhnumber } { \g@addto@macro \pdfstringdefPreHook { \zhnumClearWrapper } } \hook_gput_code:nnn { package/xCJK2uni/after } { zhnumber } { \g@addto@macro \pdfstringdefPreHook { \zhnumClearWrapper } } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhnumber} % 用于将输入的数字按照中文格式输出。 % \begin{macrocode} \NewExpandableDocumentCommand \zhnumber { +o +m } { \tl_if_novalue:nTF {#1} { \zhnum_number:e } { \zhnumberwithoptions {#1} } {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnumberwithoptions} % 带选项的用户函数。 % \begin{macrocode} \NewDocumentCommand \zhnumberwithoptions { +m +m } { \group_begin: \zhnum_set:n {#1} \zhnum_number:e {#2} \group_end: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_number:n} % \begin{macro}{\@@_number:www} % 先判断输入的是小数还是分数。 % \begin{macrocode} \zhnum_expand_wrap:wn \cs_new:Npn \zhnum_number:n #1 { \@@_number:www #1 . \q_nil . \q_stop } \cs_new:Npn \@@_number:www #1 . #2 . #3 \q_stop { \quark_if_nil:nTF {#2} { \@@_integer_or_fraction:www #1 / \q_nil / \q_stop } { \zhnum_decimal:nn {#1} {#2} } } \cs_generate_variant:Nn \zhnum_number:n { e } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@@_integer_or_fraction:www} % 判断是否输入的是分数。 % \begin{macrocode} \cs_new:Npn \@@_integer_or_fraction:www #1 / #2 / #3 \q_stop { \quark_if_nil:nTF {#2} { \zhnum_integer:n {#1} } { \@@_fraction:wwww #2 \q_mark #1 ; \q_nil ; \q_stop } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_fraction:wwww} % 对分数进行预处理。 % \begin{macrocode} \cs_new:Npn \@@_fraction:wwww #1 \q_mark #2 ; #3 ; #4 \q_stop { \quark_if_nil:nTF {#3} { \zhnum_blank_to_zero:n {#1} \zhnum_output:n { parts } \zhnum_blank_to_zero:n {#2} } { \tl_if_blank:nF {#2} { \zhnum_number:n {#2} \zhnum_output:n { and } } \zhnum_blank_to_zero:n {#1} \zhnum_output:n { parts } \zhnum_blank_to_zero:n {#3} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_decimal:nn} % 对小数进行预处理。 % \begin{macrocode} \cs_new:Npn \zhnum_decimal:nn #1#2 { \zhnum_blank_to_zero:n {#1} \zhnum_output:n { dot } \tl_if_blank:nTF {#2} { \zhnum_output:n { 0 } } { \zhnum_digits_zero:n {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_blank_to_zero:n} % 输出小数的整数位。 % \begin{macrocode} \cs_new:Npn \zhnum_blank_to_zero:n #1 { \tl_if_blank:nTF {#1} { \zhnum_output:n { 0 } } { \zhnum_number:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhnum,\zhnumberwithoptions} % 用于将 \LaTeX{} 计数器按中文格式输出。 % \begin{macrocode} \NewExpandableDocumentCommand \zhnum { +o +m } { \tl_if_novalue:nTF {#1} { \zhnum_counter:n } { \zhnumwithoptions {#1} } {#2} } \NewDocumentCommand \zhnumwithoptions { +m +m } { \group_begin: \zhnum_set:n {#1} \zhnum_counter:n {#2} \group_end: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_counter:n, \zhnum_int:n} % 可以直接通过比较 \LaTeX{} 计数器的值来得到符号和绝对值。 % \begin{macrocode} \cs_new:Npn \zhnum_counter:n #1 { \int_if_exist:cTF { c@#1 } { \exp_args:Nc \zhnum_int:n { c@#1 } } { \@@_counter_error:n {#1} } } \cs_new:Npn \@@_counter_error:n #1 { \msg_expandable_error:nnn { zhnumber } { not-counter } {#1} } \msg_new:nnn { zhnumber } { not-counter } { `#1'~is~not~a~LaTeX~counter. } \zhnum_expand_wrap:wn \cs_new:Npn \zhnum_int:n #1 { \int_compare:nNnTF {#1} > \c_zero_int { \zhnum_parse_number:f { \int_eval:n {#1} } } { \int_compare:nNnTF {#1} < \c_zero_int { \zhnum_output:n { minus } \zhnum_parse_number:f { \int_eval:n { - #1 } } } { \zhnum_output:n { 0 } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@zhnum} % 用于支持 |\pagenumbering{zhnum}|。 % \begin{macrocode} \cs_new:Npn \@zhnum { \zhnum_int:n } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_integer:n} % 对整数的处理。这个函数基本抄录自 \pkg{l3bigint} 的 \cs{__bingint_read_do:nn}。它可以 % 正确取得符号,去掉多余的零,还可以循环展开数字。但它在遇到非数字的时候就停止了 % 循环,我们可能需要非数字(例如逗号)来作为分隔符号。因此对它略作修改,跳过非数字。 % \begin{macrocode} \cs_new:Npn \zhnum_integer:n #1 { \exp_after:wN \@@_read_integer:www \int_value:w \exp_after:wN \@@_read_sign_loop:N \exp:w \exp_end_continue_f:w \use:n #1 \exp_stop_f: \q_recursion_tail \q_recursion_stop \@@_result:nn { \c_zero_int } { } ; } \cs_new:Npn \@@_read_sign_loop:N #1 { \if:w + \if:w - \exp_not:N #1 + \fi: \exp_not:N #1 \exp_after:wN \@@_read_sign_loop:N \exp:w \exp_end_continue_f:w \exp_after:wN \use:n \else: 1 \exp_after:wN ; \exp:w \exp_end_continue_f:w \exp_after:wN \@@_read_zeros_loop:N \exp_after:wN #1 \fi: } \cs_new:Npn \@@_read_zeros_loop:N #1 { \if:w 0 \exp_not:N #1 \exp_after:wN \@@_read_zeros_loop:N \exp:w \exp_end_continue_f:w \exp_after:wN \use:n \else: \exp_after:wN \@@_read_abs_loop:Nw \exp_after:wN #1 \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_read_abs_loop:Nw} % 当数字很大时,\pkg{l3bigint} 的实现会造成 \TeX{} 内存溢出: % \begin{verbatim} % ! TeX capacity exceeded, sorry [expansion depth=10000]. % \end{verbatim} % 我们在这里参考 \cs{__tl_act:NNNnn} 的实现对它进行了改进。 % \begin{macrocode} \cs_new:Npn \@@_read_abs_loop:Nw #1#2 \q_recursion_stop { \zhnum_if_digit:NTF #1 { \@@_output:nnwnn { + 1 } #1 } { \quark_if_recursion_tail_stop_do:Nn #1 { \@@_loop_end:wnn } } \exp_after:wN \@@_read_abs_loop:Nw \exp:w \exp_end_continue_f:w \use:n #2 \q_recursion_stop } \cs_new:Npn \@@_output:nnwnn #1#2#3 \@@_result:nn #4#5 { #3 \@@_result:nn { #4#1 } { #5#2 } } \cs_new:Npn \@@_loop_end:wnn #1 \@@_result:nn #2#3 { \int_eval:n {#2} ; #3 } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_read_integer:www} % |#1| 符号,|#3| 是绝对值,|#2| 是绝对值的长度。 % \begin{macrocode} \cs_new:Npn \@@_read_integer:www #1 ; #2 ; #3 ; { \int_compare:nNnTF {#2} = \c_zero_int { \zhnum_output:n { 0 } } { \int_compare:nNnF {#1} = \c_one_int { \zhnum_output:n { minus } } \zhnum_parse_number:nn {#2} {#3} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_if_digit:NTF} % 判断 |#1| 是否为数字位。 % \begin{macrocode} \cs_new:Npn \zhnum_if_digit:NTF #1 { \if_int_compare:w 9 < 1 \exp_not:N #1 \exp_stop_f: \exp_after:wN \use_i:nn \else: \exp_after:wN \use_ii:nn \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[int] % { % \zhnum_parse_number:n, % \zhnum_parse_number:nn % } % \begin{macrocode} \cs_new:Npn \zhnum_parse_number:n #1 { \exp_args:Nf \zhnum_parse_number:nn { \tl_count:n {#1} } {#1} } \cs_new:Npn \zhnum_parse_number:nn #1 { \exp_args:Nf \@@_parse_number:nnn { \int_mod:nn {#1} { 4 } } {#1} } \cs_new:Npn \@@_parse_number:nnn #1#2 { \int_compare:nNnTF {#2} < 2 { \zhnum_output:n } { \int_compare:nNnTF {#1} = \c_zero_int { \zhnum_split_number:fn { \int_eval:n { #2 / 4 - 1 } } } { \@@_split_number_aux:nnn {#1} {#2} } } } \cs_generate_variant:Nn \zhnum_parse_number:n { f } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_split_number_aux:nnn} % 为了处理的方便,在整数前面补上适当的 $0$,使其位数可以被 $4$ 整除。 % \begin{macrocode} \cs_new:Npn \@@_split_number_aux:nnn #1#2 { \exp_after:wN \@@_split_number_aux:wwn \int_value:w \int_div_truncate:nn {#2} { 4 } \if_case:w #1 \exp_stop_f: \or: \exp_after:wN \use:n \or: \exp_after:wN \use_i_ii:nnn \or: \exp_after:wN \use_i:nnn \fi: { \exp_stop_f: ; 0 } 0 0 ; } \cs_new:Npn \@@_split_number_aux:wwn #1 ; #2 ; #3 { \zhnum_split_number:nn {#1} { #2#3 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_split_number:nn} % 最后加入的 \cs{q_recursion_tail} 是停止递归的标志,而 \cs{q_nil} 用于占位。 % \begin{macrocode} \cs_new:Npn \zhnum_split_number:nn #1#2 { \zhnum_split_number:NNnNNNNw \c_true_bool \c_true_bool {#1} #2 \q_recursion_tail \q_nil \q_nil \q_nil \q_recursion_stop } \cs_generate_variant:Nn \zhnum_split_number:nn { f } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_split_number:NNnNNNNw} % 将输入的整数由高位到低位,以四位为一段进行处理。 % \begin{macrocode} \cs_new:Npn \zhnum_split_number:NNnNNNNw #1#2#3#4#5#6#7 { \quark_if_recursion_tail_stop:N #4 \int_compare:nNnTF { #4#5#6#7 } = \c_zero_int { \use_i:nn } { \bool_if:NF #1 { \zhnum_output:n { 0 } } \zhnum_process_number:NNNNNN #4#5#6#7#1#2 \zhnum_scale_map:n {#3} \int_compare:nNnTF {#7} = \c_zero_int } { \zhnum_split_number:NNfNNNNw \c_false_bool \c_true_bool } { \zhnum_split_number:NNfNNNNw \c_true_bool \c_false_bool } { \int_eval:n { #3 - 1 } } } \cs_generate_variant:Nn \zhnum_split_number:NNnNNNNw { NNf } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_process_number:NNNNNN} % 对四位数字按情况进行处理。 % \begin{macrocode} \cs_new:Npn \zhnum_process_number:NNNNNN #1#2#3#4#5#6 { \int_compare:nNnTF {#1} = \c_zero_int { \bool_if:NF #6 { \zhnum_output:n { 0 } } } { \zhnum_output:n {#1} \zhnum_output:n { 1000 } } \int_compare:nNnTF {#2} = \c_zero_int { \int_compare:nNnF { #1 * (#3#4) } = \c_zero_int { \zhnum_output:n { 0 } } } { \int_compare:nNnTF {#2} = 2 { \zhnum_output:n { 200 } } { \zhnum_output:n {#2} \zhnum_output:n { 100 } } } \int_compare:nNnTF {#3} = \c_zero_int { \int_compare:nNnF { #2 * #4 } = \c_zero_int { \zhnum_output:n { 0 } } } { \bool_lazy_all:nTF { { \int_compare_p:nNn {#3} = \c_one_int } { \int_compare_p:nNn {#1#2} = \c_zero_int } {#6} {#5} } { \zhnum_output:n { 10 } } { \int_compare:nTF { 1 < #3 < 5 } { \zhnum_output:n { #3 0 } } { \zhnum_output:n {#3} \zhnum_output:n { 10 } } } } \int_compare:nNnF {#4} = \c_zero_int { \zhnum_output:n {#4} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhdig} % 用于将 \LaTeX{} 计数器按中文数字串输出。 % \begin{macrocode} \NewExpandableDocumentCommand \zhdig { +o +m } { \tl_if_novalue:nTF {#1} { \zhnum_digits_counter:n } { \zhdigwithoptions {#1} } {#2} } \NewDocumentCommand \zhdigwithoptions { +m +m } { \group_begin: \zhnum_set:n {#1} \zhnum_digits_counter:n #1 {#2} \group_end: } \cs_new:Npn \zhnum_digits_counter:n #1 { \int_if_exist:cTF { c@#1 } { \zhnum_digits_null:v { c@#1 } } { \@@_counter_error:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@zhdig} % 用于支持 |\pagenumbering{zhdig}|。 % \begin{macrocode} \cs_new:Npn \@zhdig #1 { \zhnum_digits_null:f { \int_eval:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhdigits,\zhdigitswithoptions} % 将输入的数字输出为中文数字串输出。 % \begin{macrocode} \NewExpandableDocumentCommand \zhdigits { +s +o +m } { \tl_if_novalue:nTF {#2} { \zhnum_digits:Ne #1 } { \zhdigitswithoptions {#1} {#2} } {#3} } \NewDocumentCommand \zhdigitswithoptions { +m +m +m } { \group_begin: \zhnum_set:n {#2} \zhnum_digits:Ne #1 {#3} \group_end: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_digits_zero:n,\zhnum_digits_null:n} % 快捷方式。 % \begin{macrocode} \cs_new:Npn \zhnum_digits_zero:n { \zhnum_digits:Nn \c_true_bool } \cs_new:Npn \zhnum_digits_null:n { \zhnum_digits:Nn \c_false_bool } \cs_generate_variant:Nn \zhnum_digits_null:n { v , f } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_digits:Nn} % 与 \cs{zhnum_integer:n} 类似,但不用去掉多余的零。 % \begin{macrocode} \zhnum_expand_wrap:wn \cs_new:Npn \zhnum_digits:Nn #1#2 { \exp_after:wN \@@_read_digits:w \int_value:w \exp_after:wN \@@_read_sign_loop:NN \exp_after:wN #1 \exp:w \exp_end_continue_f:w \use:n #2 \exp_stop_f: \q_recursion_tail \q_recursion_stop } \cs_new:Npn \@@_read_sign_loop:NN #1#2 { \if:w + \if:w - \exp_not:N #2 + \fi: \exp_not:N #2 \exp_after:wN \@@_read_sign_loop:NN \exp_after:wN #1 \exp:w \exp_end_continue_f:w \exp_after:wN \use:n \else: 1 \exp_after:wN ; \exp_after:wN \@@_read_digits_loop:NN \exp_after:wN #1 \exp_after:wN #2 \fi: } \cs_new:Npn \@@_read_digits_loop:NN #1#2 { \zhnum_if_digit:NTF #2 { \@@_output_digits:NN #1#2 } { \quark_if_recursion_tail_stop:N #2 \token_if_eq_charcode:NNT #2 . { \zhnum_output:n { dot } } } \exp_after:wN \@@_read_digits_loop:NN \exp_after:wN #1 \exp:w \exp_end_continue_f:w \use:n } \cs_new:Npn \@@_read_digits:w #1 ; { \int_compare:nNnF {#1} = \c_one_int { \zhnum_output:n { minus } } } \cs_new:Npn \@@_output_digits:NN #1#2 { \zhnum_output:n { \if_int_compare:w #2 = \c_zero_int \bool_if:NTF #1 { zero } { null } \else: #2 \fi: } } \cs_generate_variant:Nn \zhnum_digits:Nn { Ne } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhdate} % 输出中文日期。 % \begin{macrocode} \NewExpandableDocumentCommand \zhdate { +s +m } { \@@_date:www #2 \q_stop \bool_if:NT #1 { \@@_week_day:www #2 \q_stop } } \cs_new:Npn \@@_date:www #1/#2/#3 \q_stop { \@@_date_aux:nnn {#1} {#2} {#3} } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhtoday} % 输出当天日期。 % \begin{macrocode} \cs_new:Npn \zhtoday { \@@_date_aux:nnn { \int_value:w \tex_year:D } { \tex_month:D } { \tex_day:D } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_date_aux:nnn} % \begin{macrocode} \cs_new:Npn \@@_date_aux:nnn { \bool_if:NTF \l_@@_time_bool { \@@_date_aux:NNnnnn \zhnum_digits_null:n \zhnum_int:n { } } { \@@_date_aux:Nnnnn \int_to_arabic:n { \l_@@_arabic_sep_tl } } } \cs_new:Npn \@@_date_aux:Nnnnn #1#2 { \@@_date_aux:NNnnnn #1#1 { \zhnum_exp_not:o {#2} } } \zhnum_expand_wrap:wn \cs_new:Npn \@@_date_aux:NNnnnn #1#2#3#4#5#6 { #1 {#4} #3 \zhnum_output:n { year } #3 #2 {#5} #3 \zhnum_output:n { month } #3 #2 {#6} #3 \zhnum_output:n { day } } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhweekday} % 输出星期 % \begin{macrocode} \cs_new:Npn \zhweekday #1 { \@@_week_day:www #1 \q_stop } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_week_day:www} % 用 Zeller 公式计算的结果 $h$ 与实际星期的关系是 $d=h+5\pmod7+1$。 % \begin{macrocode} \zhnum_expand_wrap:wn \cs_new:Npn \@@_week_day:www #1/#2/#3 \q_stop { \if_case:w \zhnum_Zeller:nnn {#1} {#2} {#3} \exp_stop_f: \zhnum_output:n { sat } \or: \zhnum_output:n { sun } \or: \zhnum_output:n { mon } \or: \zhnum_output:n { tue } \or: \zhnum_output:n { wed } \or: \zhnum_output:n { thu } \or: \zhnum_output:n { fri } \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_Zeller:nnn,\zhnum_Zeller_aux:Nnnn,\zhnum_two_digits:n} % 用 Zeller 公式\footnote{\url{http://en.wikipedia.org/wiki/Zeller's_congruence}} % 计算星期几。 % \begin{macrocode} \cs_new:Npn \zhnum_Zeller:nnn #1#2#3 { \int_compare:nNnTF { #1 \zhnum_two_digits:n {#2} \zhnum_two_digits:n {#3} } > { 1582 10 04 } { \@@_Zeller_aux:Nnnn \zhnum_Zeller_Gregorian:nnn } { \@@_Zeller_aux:Nnnn \zhnum_Zeller_Julian:nnn } {#1} {#2} {#3} } \cs_new:Npn \@@_Zeller_aux:Nnnn #1#2#3#4 { \int_compare:nNnTF {#3} < 3 { #1 { #2 - 1 } { #3 + 12 } {#4} } { #1 {#2} {#3} {#4} } } \cs_new:Npn \zhnum_two_digits:n #1 { \int_compare:nNnT {#1} < { 10 } { 0 } \int_eval:n {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_Zeller_Gregorian:nnn} % 格里历(\zhdate{1582/10/15}及以后)的计算公式 % \[ % h = \biggl(q + \biggl\lfloor\frac{26(m+1)}{10}\biggr\rfloor + Y + % \biggl\lfloor\frac Y4\biggr\rfloor + 6\biggl\lfloor\frac Y{100}\biggr\rfloor % + \biggl\lfloor\frac Y{400}\biggr\rfloor\biggr) \pmod 7 % \] % 其中 $Y$ 为年,$m$ 为月,$q$ 为日;若 $m=1,2$,则令 $m\mathbin{{+}{=}}12$,同时 $Y\mathop{--}{}$。 % \begin{macrocode} \cs_new:Npn \zhnum_Zeller_Gregorian:nnn #1#2#3 { \int_mod:nn { (#3) + \int_div_truncate:nn { 26 * ( #2 + 1 ) } { 10 } + (#1) + \int_div_truncate:nn {#1} { 4 } + 6 * \int_div_truncate:nn {#1} { 100 } + \int_div_truncate:nn {#1} { 400 } } { 7 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_Zeller_Julian:nnn} % 儒略历(\zhdate{1582/10/04}及以前)的计算公式 % \[ % h = \biggl(q + \biggl\lfloor\frac{26(m+1)}{10}\biggr\rfloor + Y + % \biggl\lfloor\frac Y4\biggr\rfloor + 5\biggr) \pmod 7 % \] % \begin{macrocode} \cs_new:Npn \zhnum_Zeller_Julian:nnn #1#2#3 { \int_mod:nn { (#3) + \int_div_truncate:nn { 26 * ( #2 + 1 ) } { 10 } + (#1) + \int_div_truncate:nn {#1} { 4 } + 5 } { 7 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhtime} % 输出时间。 % \begin{macrocode} \zhnum_expand_wrap:wn \cs_new:Npn \zhtime #1 { \@@_time:ww #1 \q_stop } \use:e { \cs_new:Npn \exp_not:N \@@_time:ww #1 \c_colon_str #2 \exp_not:N \q_stop } { \@@_time_aux:nn {#1} {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhcurrtime} % 输出当前时间。 % \begin{macrocode} \zhnum_expand_wrap:wn \cs_new:Npn \zhcurrtime { \@@_time_aux:nn { \int_div_truncate:nn \tex_time:D { 60 } } { \int_mod:nn \tex_time:D { 60 } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_time_aux:nn,\@@_time_aux:Nnnn} % \begin{macrocode} \cs_new:Npn \@@_time_aux:nn { \bool_if:NTF \l_@@_time_bool { \@@_time_aux:Nnnn \zhnum_int:n { } } { \@@_time_aux:Nnnn \int_to_arabic:n { \l_@@_arabic_sep_tl } } } \cs_new:Npn \@@_time_aux:Nnnn #1#2#3#4 { #1 {#3} #2 \zhnum_output:n { hour } #2 #1 {#4} #2 \zhnum_output:n { minute } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_scale_map:n,\zhnum_scale_map_loop:n} % 大数系统的映射。 % \begin{macrocode} \cs_new:Npn \zhnum_scale_map:n #1 { \tl_if_exist:cTF { l_@@_s #1 _tl } { \zhnum_output:n { s #1 } } { \zhnum_scale_map_hook:n {#1} } } \cs_new:Npn \zhnum_scale_map_loop:n #1 { \zhnum_scale_map:n { \int_mod:nn {#1} \l_@@_scale_int } } \cs_generate_variant:Nn \zhnum_scale_map:n { f } \int_new:N \l_@@_scale_int \int_set:Nn \l_@@_scale_int { 11 } \cs_new_eq:NN \zhnum_scale_map_hook:n \zhnum_scale_map_loop:n \tl_new:c { l_@@_s 0 _tl } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhnumExtendScaleMap} % 扩展进位系统。 % \begin{macrocode} \NewDocumentCommand \zhnumExtendScaleMap { > { \TrimSpaces } +o +m } { \int_zero:N \l_@@_tmp_int \clist_map_function:nN {#2} \zhnum_set_scale:n \tl_if_novalue:nF {#1} { \cs_set:Npn \zhnum_scale_map_hook:n ##1 {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_set_scale:n} % \begin{macrocode} \cs_new_protected:Npn \zhnum_set_scale:n #1 { \int_incr:N \l_@@_tmp_int \exp_args:Nc \@@_set_scale:Nn { l_@@_s \int_eval:n { \l_@@_tmp_int + 11 } _tl } {#1} } \cs_new_protected:Npn \@@_set_scale:Nn #1 { \tl_if_exist:NF #1 { \tl_new:N #1 \int_incr:N \l_@@_scale_int } \tl_set:Nn #1 } \int_new:N \l_@@_tmp_int % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_ganzhi_normal:nnn} % 保证干支的参数为正数。 % \begin{macrocode} \zhnum_expand_wrap:wn \cs_new:Npn \zhnum_ganzhi_normal:nnn #1#2#3 { \int_compare:nNnF {#1} < \c_one_int { \cs_if_free:cF { l_@@_ #2 _ #1 _tl } { \zhnum_output:n { #2 _ #1 } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_ganzhi_cyclic:nnn} % \begin{macro}{\@@_ganzhi_cyclic_mod:nnnn} % 对超出范围的数字取模,参数 |0| 的结果是空值。 % \begin{macrocode} \zhnum_expand_wrap:wn \cs_new:Npn \zhnum_ganzhi_cyclic:nnn #1#2#3 { \int_compare:nNnF {#1} = \c_zero_int { \tl_if_exist:cTF { l_@@_ #2 _ #1 _tl } { \zhnum_output:n { #2 _ #1 } } { \@@_ganzhi_cyclic_mod:fnnn { \int_mod:nn {#1} {#3} } {#1} {#2} {#3} } } } \cs_new:Npn \@@_ganzhi_cyclic_mod:nnnn #1#2#3#4 { \int_compare:nNnTF {#2} > \c_zero_int { \zhnum_output:n { #3 _ #1 } } { \int_compare:nNnTF {#1} = \c_zero_int { \zhnum_output:n { #3 _ 1 } } { \zhnum_output:n { #3 _ \int_eval:n { #1 + #4 + 1 } } } } } \cs_generate_variant:Nn \@@_ganzhi_cyclic_mod:nnnn { f } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[int]{\zhnum_ganzhi:nnn} % 默认不对超出范围的数字取模。 % \begin{macrocode} \cs_new_eq:NN \zhnum_ganzhi:nnn \zhnum_ganzhi_normal:nnn \cs_generate_variant:Nn \zhnum_ganzhi:nnn { f } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhtiangan} % 天干。 % \begin{macrocode} \cs_new:Npn \zhtiangan #1 { \zhnum_ganzhi:fnn { \int_eval:n {#1} } { tiangan } { 10 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhdizhi} % 地支。 % \begin{macrocode} \cs_new:Npn \zhdizhi #1 { \zhnum_ganzhi:fnn { \int_eval:n {#1} } { dizhi } { 12 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhganzhi} % 干支。 % \begin{macrocode} \cs_new:Npn \zhganzhi #1 { \zhnum_ganzhi:fnn { \int_eval:n {#1} } { ganzhi } { 60 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhganzhinian} % 干支纪年。 % \begin{macrocode} \cs_new:Npn \zhganzhinian #1 { \zhnum_ganzhi_nian:f { \int_eval:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_ganzhi_nian:n} % 干支纪年。公元元年是 |\zhganzhi{58}|。 % \begin{macrocode} \zhnum_expand_wrap:wn \cs_new:Npn \zhnum_ganzhi_nian:n #1 { \int_compare:nNnTF {#1} > \c_zero_int { \zhnum_output:n { ganzhi_ \int_mod:nn { #1 + 57 } { 60 } } } { \int_compare:nNnF {#1} = \c_zero_int { \zhnum_output:n { ganzhi_ \int_eval:n { \int_mod:nn { #1 - 2 } { 60 } + 60 } } } } } \cs_generate_variant:Nn \zhnum_ganzhi_nian:n { f } % \end{macrocode} % \end{macro} % % 根据需要设置中文阿拉伯数字。 % \begin{macrocode} \tl_new:N \l_@@_kv_tl \tl_new:N \l_@@_tmp_tl \group_begin: \tl_build_begin:N \l_@@_kv_tl \int_step_inline:nn { 10 } { \tl_new:c { l_@@_ #1 _tl } \tl_build_put_right:Nx \l_@@_kv_tl { #1 .tl_set:N = \exp_not:c { l_@@_normal_ #1 _tl } , F#1 .tl_set:N = \exp_not:c { l_@@_financial_ #1 _tl } , E \int_eval:n { #1 * 4 } .tl_set:N = \exp_not:c { l_@@_ s#1 _tl } , } } \clist_map_inline:nn { 0 , 100 , 1000 } { \tl_new:c { l_@@_ #1 _tl } \tl_build_put_right:Nx \l_@@_kv_tl { #1 .tl_set:N = \exp_not:c { l_@@_normal_ #1 _tl } , F#1 .tl_set:N = \exp_not:c { l_@@_financial_ #1 _tl } , } } \clist_map_inline:nn { 20 , 30 , 40 , 200 , dot , and , parts , year , month , day , hour , minute } { \tl_build_put_right:Nx \l_@@_kv_tl { #1 .tl_set:N = \exp_not:c { l_@@_ #1 _tl } , } } \tl_build_put_right:Nx \l_@@_kv_tl { - .tl_set:N = \exp_not:N \l_@@_minus_tl , -0 .tl_set:N = \exp_not:N \l_@@_null_tl , E2 .tl_set:N = \exp_not:c { l_@@_normal_ 100 _tl } , E3 .tl_set:N = \exp_not:c { l_@@_normal_ 1000 _tl } , FE2 .tl_set:N = \exp_not:c { l_@@_financial_ 100 _tl } , FE3 .tl_set:N = \exp_not:c { l_@@_financial_ 1000 _tl } , E44 .tl_set:N = \exp_not:c { l_@@_ s11 _tl } } \tl_build_get:NN \l_@@_kv_tl \l_@@_tmp_tl \cs_set:Npn \@@_tmp:w #1 . #2 \q_stop { , #1 .groups:n = { user } } \clist_map_inline:Nn \l_@@_tmp_tl { \tl_build_put_right:Nx \l_@@_kv_tl { \@@_tmp:w #1 \q_stop } } \tl_build_put_right:Nn \l_@@_kv_tl { , weekday .tl_set:N = \l_@@_weekday_tl , weekday .groups:n = { user , pre , weekday } , } \clist_map_inline:nn { mon , tue , wed , thu , fri , sat , sun } { \tl_build_put_right:Nx \l_@@_kv_tl { #1 .tl_set:N = \exp_not:c { l_@@_ #1 _tl } , #1 .groups:n = { user , pos , day } , } } \int_step_inline:nn { 10 } { \tl_build_put_right:Nx \l_@@_kv_tl { T#1 .tl_set:N = \exp_not:c { l_@@_ganzhi_ #1 _tl } , T#1 .groups:n = { user , pre , tiandi } , } } \int_step_inline:nn { 12 } { \tl_build_put_right:Nx \l_@@_kv_tl { D#1 .tl_set:N = \exp_not:c { l_@@_dizhi_ #1 _tl } , D#1 .groups:n = { user , pre , tiandi } , } } \int_step_inline:nn { 60 } { \tl_build_put_right:Nx \l_@@_kv_tl { GZ#1 .tl_set:N = \exp_not:c { l_@@_ganzhi_ #1 _tl } , GZ#1 .groups:n = { user , pos , ganzhi } , } } \tl_build_end:N \l_@@_kv_tl \exp_args:NNno \group_end: \keys_define:nn { zhnum / options } { \l_@@_kv_tl } % \end{macrocode} % % \begin{macro}[int] % { % \zhnum_set_digits_map:nn, % \zhnum_set_digits_map:nnn, % \zhnum_set_financial_map:nn, % \zhnum_set_financial_map:nnn, % \zhnum_set_tiangan_map:nn, % \zhnum_set_dizhi_map:nn % } % \begin{variable} % { % \l_@@_cfg_map_prop, % \l_@@_cfg_map_var_prop, % \l_@@_cfg_map_finan_prop, % \l_@@_cfg_map_ganzhi_prop % } % 将配置文件中的中文数字保存到 \texttt{prop} 变量中。 % \begin{macrocode} \cs_new_protected:Npn \zhnum_set_digits_map:nn #1 { \prop_put:Nnn \l_@@_cfg_map_prop {#1} } \cs_new_protected:Npn \zhnum_set_digits_map:nnn #1#2#3 { \prop_put_if_new:Nnn \l_@@_cfg_map_prop {#1} {#3} \prop_put:Nnn \l_@@_cfg_map_var_prop {#1_#2} {#3} } \cs_new_protected:Npn \zhnum_set_financial_map:nn #1 { \prop_put:Nnn \l_@@_cfg_map_finan_prop {#1} } \cs_new_protected:Npn \zhnum_set_financial_map:nnn #1#2#3 { \prop_put_if_new:Nnn \l_@@_cfg_map_finan_prop {#1} {#3} \prop_put:Nnn \l_@@_cfg_map_var_prop { financial_#1_#2 } {#3} } \cs_new_protected:Npn \zhnum_set_tiangan_map:nn #1 { \prop_put:Nnn \l_@@_cfg_map_ganzhi_prop { tiangan_#1 } } \cs_new_protected:Npn \zhnum_set_dizhi_map:nn #1 { \prop_put:Nnn \l_@@_cfg_map_ganzhi_prop { dizhi_#1 } } \prop_new:N \l_@@_cfg_map_prop \prop_new:N \l_@@_cfg_map_var_prop \prop_new:N \l_@@_cfg_map_finan_prop \prop_new:N \l_@@_cfg_map_ganzhi_prop % \end{macrocode} % \end{variable} % \end{macro} % % \begin{macro}[int] % { % \zhnum_parse_config:, % \zhnum_check_simp:nn, % \zhnum_check_financial:nn, % \zhnum_set_week_day: % } % 将 \texttt{prop} 表转化到单独的 \texttt{tl} 变量。 % \begin{macrocode} \cs_new_protected:Npn \zhnum_parse_config: { \tl_clear_new:N \l_@@_reset_tl \tl_clear_new:N \l_@@_reset_simp_tl \tl_clear_new:N \l_@@_reset_trad_tl \tl_clear_new:N \l_@@_set_ancient_tl \tl_clear_new:N \l_@@_set_normal_tl \tl_clear_new:N \l_@@_reset_ancient_tl \tl_clear_new:N \l_@@_reset_normal_tl \tl_clear_new:N \l_@@_reset_financial_tl \prop_map_function:NN \l_@@_cfg_map_prop \zhnum_check_simp:nn \zhnum_set_ganzhi: \zhnum_reset_all: } \cs_new_protected:Npn \zhnum_check_simp:nn #1#2 { \prop_get:NnNTF \l_@@_cfg_map_var_prop { #1_ancient } \l_@@_ancient_tl { \@@_add_reset_ancient:nN {#1} \l_@@_ancient_tl } { \@@_check_simp_aux:nn {#2} {#1} \prop_get:NnNT \l_@@_cfg_map_finan_prop {#1} \l_@@_tmp_tl { \exp_args:No \@@_check_simp_aux:nn { \l_@@_tmp_tl } { financial_ #1 } \@@_add_reset_financial:n {#1} } } } \cs_new_protected:Npn \@@_check_simp_aux:nn #1#2 { \prop_get:NnNTF \l_@@_cfg_map_var_prop { #2 _trad } \l_@@_trad_tl { \prop_get:NnNF \l_@@_cfg_map_var_prop { #2 _simp } \l_@@_simp_tl { \tl_set:Nn \l_@@_simp_tl {#1} } \@@_add_reset_simp:nNN {#2} \l_@@_simp_tl \l_@@_trad_tl } { \@@_add_reset:nn {#2} {#1} } } \tl_new:N \l_@@_simp_tl \tl_new:N \l_@@_trad_tl \tl_new:N \l_@@_ancient_tl \cs_new_protected:Npn \@@_add_reset:nn #1#2 { \tl_put_right:Nx \l_@@_reset_tl { \tl_set:Nn \exp_not:c { l_@@_ #1 _tl } { \exp_not:n {#2} } } } \cs_new_protected:Npn \@@_add_reset_simp:nNN #1#2#3 { \tl_put_right:Nx \l_@@_reset_simp_tl { \tl_set:Nn \exp_not:c { l_@@_ #1 _tl } { \exp_not:o {#2} } } \tl_put_right:Nx \l_@@_reset_trad_tl { \tl_set:Nn \exp_not:c { l_@@_ #1 _tl } { \exp_not:o {#3} } } } \cs_new_protected:Npn \@@_add_reset_financial:n #1 { \tl_put_right:Nx \l_@@_set_normal_tl { \tl_set_eq:NN \exp_not:c { l_@@_normal_ #1 _tl } \exp_not:c { l_@@_ #1 _tl } } \tl_put_right:Nx \l_@@_reset_normal_tl { \tl_set_eq:NN \exp_not:c { l_@@_ #1 _tl } \exp_not:c { l_@@_normal_ #1 _tl } } \tl_put_right:Nx \l_@@_reset_financial_tl { \tl_set_eq:NN \exp_not:c { l_@@_ #1 _tl } \exp_not:c { l_@@_financial_ #1 _tl } } } \cs_new_protected:Npn \@@_add_reset_ancient:nN #1#2 { \tl_put_right:Nx \l_@@_reset_ancient_tl { \tl_set:Nn \exp_not:c { l_@@_ #1 _tl } { \exp_not:o {#2} } } \tl_put_right:Nx \l_@@_set_ancient_tl { \tl_concat:NNN \exp_not:c { l_@@_ #1 _tl } \exp_not:c { l_@@_ \str_head:n {#1} _tl } \exp_not:c { l_@@_ 1 \str_tail:n {#1} _tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int] % { % \zhnum_set_week_day:, % \zhnum_reset_week_day: % } % \begin{macrocode} \cs_new_protected:Npn \zhnum_set_week_day: { \cs_set_protected:Npx \zhnum_reset_week_day: { \@@_set_week_day:nn { mon } { 1 } \@@_set_week_day:nn { tue } { 2 } \@@_set_week_day:nn { wed } { 3 } \@@_set_week_day:nn { thu } { 4 } \@@_set_week_day:nn { fri } { 5 } \@@_set_week_day:nn { sat } { 6 } \@@_set_week_day:nn { sun } { day } } } \cs_new_eq:NN \zhnum_reset_week_day: \prg_do_nothing: \cs_new:Npn \@@_set_week_day:nn #1#2 { \tl_set:Nx \exp_not:c { l_@@_ #1 _tl } { \exp_not:N \exp_not:o { \exp_not:N \l_@@_weekday_tl } \exp_not:N \exp_not:n { \exp_not:v { l_@@_ #2 _tl } } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int] % { % \zhnum_set_ganzhi:, % \zhnum_reset_ganzhi: % } % \begin{macrocode} \cs_new_protected:Npn \zhnum_set_ganzhi: { \prop_map_function:NN \l_@@_cfg_map_ganzhi_prop \@@_add_reset:nn } \cs_new_protected:Npn \@@_reset_ganzhi:nn #1#2 { \tl_set:cn { l_@@_ #1 _tl } {#2} } \cs_new:Npn \zhnum_zero_mod:nn #1#2 { \exp_args:Nf \@@_zero_mod_aux:nn { \int_mod:nn {#1} {#2} } {#2} } \cs_new:Npn \@@_zero_mod_aux:nn #1#2 { \int_compare:nNnTF {#1} = \c_zero_int {#2} {#1} } \tl_new:c { l_@@_dizhi_ 0 _tl } \tl_new:c { l_@@_ganzhi_ 0 _tl } \tl_new:c { l_@@_tiangan_ 0 _tl } \group_begin: \cs_set:Npn \@@_tmp:w #1 { \tl_concat:NNN \exp_not:c { l_@@_ganzhi_ #1 _tl } \exp_not:c { l_@@_tiangan_ \zhnum_zero_mod:nn {#1} { 10 } _tl } \exp_not:c { l_@@_dizhi_ \zhnum_zero_mod:nn {#1} { 12 } _tl } } \cs_new_protected:Npx \zhnum_reset_ganzhi: { \tl_set_eq:NN \exp_not:c { l_@@_dizhi_ 0 _tl } \exp_not:c { l_@@_dizhi_ 12 _tl } \tl_set_eq:NN \exp_not:c { l_@@_tiangan_ 0 _tl } \exp_not:c { l_@@_tiangan_ 10 _tl } \int_step_function:nN { 60 } \@@_tmp:w \tl_set_eq:NN \exp_not:c { l_@@_ganzhi_ 0 _tl } \exp_not:c { l_@@_ganzhi_ 60 _tl } } \group_end: % \end{macrocode} % \end{macro} % % \begin{macro}[int] % { % \zhnum_reset_config:, % \zhnum_reset_all:, % \zhnum_reset_style: % } % \begin{macrocode} \cs_new_protected:Npn \zhnum_reset_config: { \zhnum_load_cfg:o { \l_@@_encoding_str } } \cs_new_protected:Npn \zhnum_reset_all: { \zhnum_reset_main: \zhnum_reset_simp: \zhnum_set_week_day: \zhnum_reset_week_day: \zhnum_reset_ganzhi: \zhnum_reset_normal: } \cs_new_protected:Npn \zhnum_reset_main: { \tl_use:N \l_@@_reset_tl \tl_use:N \l_@@_set_normal_tl \tl_concat:NNN \l_@@_reset_normal_tl \l_@@_reset_normal_tl \c_@@_set_zero_tl \tl_concat:NNN \l_@@_reset_financial_tl \l_@@_reset_financial_tl \c_@@_set_zero_tl \tl_concat:NNN \l_@@_reset_financial_tl \l_@@_reset_financial_tl \l_@@_set_ancient_tl } \tl_const:Nx \c_@@_set_zero_tl { \tl_set_eq:NN \exp_not:N \l_@@_zero_tl \exp_not:c { l_@@_0_tl } } \tl_new:N \l_@@_zero_tl \cs_new_protected:Npn \zhnum_reset_style: { \zhnum_reset_simp: \zhnum_reset_normal: } \cs_new_protected:Npn \zhnum_reset_simp: { \bool_if:NTF \l_@@_simp_bool { \tl_use:N \l_@@_reset_simp_tl } { \tl_use:N \l_@@_reset_trad_tl } } \cs_new_protected:Npn \zhnum_reset_normal: { \bool_if:NTF \l_@@_normal_bool { \tl_use:N \l_@@_reset_normal_tl \@@_reset_ancient: \@@_reset_zero: } { \tl_use:N \l_@@_reset_financial_tl } } \cs_new_protected:Npn \@@_reset_ancient: { \bool_if:NTF \l_@@_ancient_bool { \tl_use:N \l_@@_reset_ancient_tl } { \tl_use:N \l_@@_set_ancient_tl } } \cs_new_protected:Npx \@@_reset_zero: { \exp_not:n { \bool_if:NT \l_@@_null_bool } { \tl_set_eq:NN \exp_not:c { l_@@_0_tl } \exp_not:N \l_@@_null_tl } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_load_cfg:n} % 根据选定编码载入配置文件。 % \begin{macrocode} \cs_new_protected:Npn \zhnum_load_cfg:n #1 { \zhnum_set_cfg_name:Nn \l_@@_cfg_str {#1} \str_if_eq:NNTF \l_@@_cfg_str \l_@@_last_cfg_str { \zhnum_reset_all: } { \zhnum_update_cfg:n {#1} \zhnum_parse_config: } } \cs_generate_variant:Nn \zhnum_load_cfg:n { o } \cs_new_protected:Npn \zhnum_update_cfg:n #1 { \prop_if_exist:cTF { g_@@_cfg_ \l_@@_cfg_str _prop } { \@@_set_cfg_prop: } { \zhnum_input_cfg:n {#1} } } \cs_new_protected:Npn \@@_set_cfg_prop: { \str_set_eq:NN \l_@@_last_cfg_str \l_@@_cfg_str \@@_update_cfg_prop:N \prop_set_eq:Nc } \cs_new_protected:Npn \zhnum_input_cfg:n #1 { \file_get_full_name:nNTF { zhnumber - #1 .cfg } \l_@@_cfg_file_tl { \bool_set_false:N \l_@@_reset_bool \@@_update_cfg_prop:N \@@_prop_initial:Nn \group_begin: \zhnum_set_catcode: \exp_args:No \file_input:n { \l_@@_cfg_file_tl } \@@_update_cfg_prop:N \@@_prop_gset_eq:Nn \group_end: \@@_set_cfg_prop: } { \msg_error:nnx { zhnumber } { file-not-found } {#1} } } \tl_new:N \l_@@_cfg_file_tl \cs_new_protected:Npn \@@_update_cfg_prop:N { \exp_args:No \@@_update_cfg_prop_aux:nN { \l_@@_cfg_str } } \cs_new_protected:Npn \@@_update_cfg_prop_aux:nN #1#2 { #2 \l_@@_cfg_map_prop { g_@@_cfg_ #1 _prop } #2 \l_@@_cfg_map_var_prop { g_@@_cfg_var_ #1 _prop } #2 \l_@@_cfg_map_finan_prop { g_@@_cfg_finan_ #1 _prop } #2 \l_@@_cfg_map_ganzhi_prop { g_@@_cfg_ganzhi_ #1 _prop } } \cs_new_protected:Npn \@@_prop_initial:Nn #1#2 { \prop_clear:N #1 \prop_new:c {#2} } \cs_new_protected:Npn \@@_prop_gset_eq:Nn #1#2 { \prop_gset_eq:cN {#2} #1 } \str_new:N \l_@@_cfg_str \str_new:N \l_@@_last_cfg_str \bool_new:N \l_@@_reset_bool \msg_new:nnnn { zhnumber } { file-not-found } { File~`#1'~not~found. } { The~requested~file~could~not~be~found~in~the~current~directory,~ in~the~TeX~search~path~or~in~the~LaTeX~search~path. } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\c_@@_unicode_engine_bool} % 使用 \upTeX{} 的时候,也不必将汉字的首字符设置为活动字符。判断 |^^^^0021| 是否为 % 单个记号的办法对 \upTeX{} 不适用。 % \begin{macrocode} \bool_const:Nn \c_@@_unicode_engine_bool { \bool_lazy_any_p:n { { \sys_if_engine_xetex_p: } { \sys_if_engine_luatex_p: } { \sys_if_engine_uptex_p: } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int] % { % \zhnum_set_catcode:, % \zhnum_set_cfg_name:Nn, % \zhnum_reset_config: % } % 设置与恢复配置文件前后的 catcode。\pdfLaTeX{} 需要将汉字的首字节设置为活动字符。 % \begin{macrocode} \bool_if:NTF \c_@@_unicode_engine_bool { \cs_new_eq:NN \zhnum_set_catcode: \prg_do_nothing: \cs_new_protected:Npn \zhnum_set_cfg_name:Nn #1#2 { \str_set:Nx \l_@@_encoding_str {#2} \str_set_eq:NN #1 \l_@@_encoding_str } } { \cs_new_protected:Npn \zhnum_set_catcode: { \bool_if:NTF \l_@@_active_char_bool { \zhnum_set_active: } { \zhnum_set_other: } } \cs_new_protected:Npx \zhnum_set_active: { \int_step_function:nnN { 128 } { 255 } \char_set_catcode_active:n } \cs_new_protected:Npx \zhnum_set_other: { \int_step_function:nnN { 128 } { 255 } \char_set_catcode_other:n } \cs_new_protected:Npn \zhnum_set_cfg_name:Nn #1#2 { \str_set:Nx \l_@@_encoding_str {#2} \str_set:Nx #1 { \l_@@_encoding_str \bool_if:NTF \l_@@_active_char_bool { / active } { / other } } } \bool_new:N \l_@@_active_char_bool \bool_set_true:N \l_@@_active_char_bool } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\zhnum_set_encoding:n} % 设置编码。 % \begin{macrocode} \cs_new_protected:Npn \zhnum_set_encoding:n #1 { \str_set:Nx \l_@@_encoding_str { \str_lowercase:n {#1} } \zhnum_load_cfg:o { \l_@@_encoding_str } } \str_new:N \l_@@_encoding_str % \end{macrocode} % \end{macro} % % \begin{macro}{encoding,style,null,reset} % 宏包设置选项。 % \begin{macrocode} \keys_define:nn { zhnum / options } { encoding .choices:nn = { UTF8 , GBK , Big5 } { \exp_args:No \zhnum_set_encoding:n { \l_keys_choice_tl } } , encoding .default:n = { GBK } , encoding / Bg5 .meta:n = { encoding = Big5 } , encoding / unknown .code:n = { \msg_error:nnn { zhnumber } { encoding-invalid } {#1} } , style .multichoice: , style / Normal .code:n = { \bool_set_false:N \l_@@_ancient_bool \bool_set_true:N \l_@@_normal_bool } , style / Financial .code:n = { \bool_set_false:N \l_@@_ancient_bool \bool_set_false:N \l_@@_normal_bool } , style / Ancient .code:n = { \bool_set_true:N \l_@@_ancient_bool \bool_set_true:N \l_@@_normal_bool } , style / Simplified .code:n = { \bool_set_true:N \l_@@_simp_bool } , style / Traditional .code:n = { \bool_set_false:N \l_@@_simp_bool } , style .default:n = { Normal , Simplified } , style .groups:n = { style } , null .bool_set:N = \l_@@_null_bool , null .groups:n = { style } , time .choice: , time / Chinese .code:n = { \bool_set_true:N \l_@@_time_bool } , time / Arabic .code:n = { \bool_set_false:N \l_@@_time_bool } , time .default:n = { Arabic } , reset .bool_set:N = \l_@@_reset_bool , activechar .bool_set:N = \l_@@_active_char_bool , ganzhi-cyclic .choice: , ganzhi-cyclic / true .code:n = { \cs_set_eq:NN \zhnum_ganzhi:nnn \zhnum_ganzhi_cyclic:nnn } , ganzhi-cyclic / false.code:n = { \cs_set_eq:NN \zhnum_ganzhi:nnn \zhnum_ganzhi_normal:nnn } , ganzhi-cyclic .default:n = { true } , arabicsep .tl_set:N = \l_@@_arabic_sep_tl } \bool_new:N \l_@@_simp_bool \bool_new:N \l_@@_normal_bool \bool_new:N \l_@@_ancient_bool \msg_new:nnnn { zhnumber } { encoding-invalid } { The~encoding~`#1'~is~invalid. } { Available~encodings~are~`UTF8',~`GBK'~and~`Big5'. } % \end{macrocode} % \end{macro} % % \begin{macro}{\zhnumsetup} % 在文档中设置 \pkg{zhnumber} 的接口。 % \begin{macrocode} \NewDocumentCommand \zhnumsetup { +m } { \zhnum_set:n {#1} \tex_ignorespaces:D } \cs_new_protected:Npn \zhnum_set:n #1 { \bool_set_false:N \l_@@_reset_bool \keys_set_filter:nnnN { zhnum / options } { style , user } {#1} \l_@@_kv_tl \tl_if_empty:NF \l_@@_kv_tl { \@@_set_style: } \bool_if:NT \l_@@_reset_bool { \zhnum_reset_config: } } \cs_new_protected:Npn \@@_set_style: { \keys_set_filter:nnoN { zhnum / options } { user } { \l_@@_kv_tl } \l_@@_tmp_tl \tl_if_empty:NTF \l_@@_tmp_tl { \zhnum_reset_style: } { \tl_if_eq:NNF \l_@@_tmp_tl \l_@@_kv_tl { \zhnum_reset_style: } \bool_if:NF \l_@@_reset_bool { \@@_set_user: } } } \cs_new_protected:Npn \@@_set_user: { \keys_set_filter:nnoN { zhnum / options } { pre , pos } { \l_@@_tmp_tl } \l_@@_kv_tl \tl_if_eq:NNF \l_@@_kv_tl \l_@@_tmp_tl { \zhnum_reset_normal: } \tl_if_empty:NF \l_@@_kv_tl { \@@_set_pre_pos: } } \cs_new_protected:Npn \@@_set_pre_pos: { \keys_set_filter:nnoN { zhnum / options } { pos } { \l_@@_kv_tl } \l_@@_tmp_tl \tl_if_eq:NNF \l_@@_tmp_tl \l_@@_kv_tl { \zhnum_reset_week_day: \zhnum_reset_ganzhi: } \tl_if_empty:NF \l_@@_kv_tl { \keys_set:no { zhnum / options } { \l_@@_kv_tl } } } \cs_generate_variant:Nn \keys_set_filter:nnnN { nno } % \end{macrocode} % \end{macro} % % 初始化设置和执行宏包选项。 % \begin{macrocode} \keys_set:nn { zhnum / options } { style , time , arabicsep = { ~ } } \cs_if_exist:NTF \ProcessKeyOptions { \ProcessKeyOptions [ zhnum / options ] } { \RequirePackage { l3keys2e } \ProcessKeysOptions { zhnum / options } } % \end{macrocode} % % 如果没有选定编码,则选用 |UTF8|。 % \begin{macrocode} \str_if_empty:NTF \l_@@_encoding_str { \zhnum_set_encoding:n { UTF8 } } { \zhnum_reset_style: } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \section{中文数字配置文件} % \label{sec:zhnum-map} % % \begin{macrocode} %<*config> % \end{macrocode} % % \begin{macrocode} %<*!big5> \zhnum_set_digits_map:nnn { minus } { simp } { 负 } \zhnum_set_digits_map:nnn { minus } { trad } { 負 } % %<*big5> \zhnum_set_digits_map:nn { minus } { 負 } % \zhnum_set_digits_map:nn { 0 } { 零 } %<*!big5> \zhnum_set_digits_map:nn { null } { 〇 } % %<*big5> \zhnum_set_digits_map:nn { null } { ○ } % \zhnum_set_digits_map:nn { 1 } { 一 } \zhnum_set_digits_map:nn { 2 } { 二 } \zhnum_set_digits_map:nn { 3 } { 三 } \zhnum_set_digits_map:nn { 4 } { 四 } \zhnum_set_digits_map:nn { 5 } { 五 } \zhnum_set_digits_map:nn { 6 } { 六 } \zhnum_set_digits_map:nn { 7 } { 七 } \zhnum_set_digits_map:nn { 8 } { 八 } \zhnum_set_digits_map:nn { 9 } { 九 } \zhnum_set_digits_map:nn { 10 } { 十 } \zhnum_set_digits_map:nn { 100 } { 百 } \zhnum_set_digits_map:nn { 1000 } { 千 } \zhnum_set_digits_map:nnn { 20 } { ancient } { 廿 } \zhnum_set_digits_map:nnn { 30 } { ancient } { 卅 } \zhnum_set_digits_map:nnn { 40 } { ancient } { 卌 } \zhnum_set_digits_map:nnn { 200 } { ancient } { 皕 } %<*!big5> \zhnum_set_digits_map:nnn { dot } { simp } { 点 } \zhnum_set_digits_map:nnn { dot } { trad } { 點 } % %<*big5> \zhnum_set_digits_map:nn { dot } { 點 } % \zhnum_set_digits_map:nn { and } { 又 } \zhnum_set_digits_map:nn { parts } { 分之 } %<*!big5> \zhnum_set_digits_map:nnn { s1 } { simp } { 万 } \zhnum_set_digits_map:nnn { s1 } { trad } { 萬 } \zhnum_set_digits_map:nnn { s2 } { simp } { 亿 } \zhnum_set_digits_map:nnn { s2 } { trad } { 億 } % %<*big5> \zhnum_set_digits_map:nn { s1 } { 萬 } \zhnum_set_digits_map:nn { s2 } { 億 } % \zhnum_set_digits_map:nn { s3 } { 兆 } \zhnum_set_digits_map:nn { s4 } { 京 } \zhnum_set_digits_map:nn { s5 } { 垓 } \zhnum_set_digits_map:nn { s6 } { 秭 } \zhnum_set_digits_map:nn { s7 } { 穰 } %<*!big5> \zhnum_set_digits_map:nnn { s8 } { simp } { 沟 } \zhnum_set_digits_map:nnn { s8 } { trad } { 溝 } \zhnum_set_digits_map:nnn { s9 } { simp } { 涧 } \zhnum_set_digits_map:nnn { s9 } { trad } { 澗 } % %<*big5> \zhnum_set_digits_map:nn { s8 } { 溝 } \zhnum_set_digits_map:nn { s9 } { 澗 } % \zhnum_set_digits_map:nn { s10 } { 正 } %<*!big5> \zhnum_set_digits_map:nnn { s11 } { simp } { 载 } \zhnum_set_digits_map:nnn { s11 } { trad } { 載 } % %<*big5> \zhnum_set_digits_map:nn { s11 } { 載 } % \zhnum_set_digits_map:nn { year } { 年 } \zhnum_set_digits_map:nn { month } { 月 } \zhnum_set_digits_map:nn { day } { 日 } %<*!big5> \zhnum_set_digits_map:nnn { hour } { simp } { 时 } \zhnum_set_digits_map:nnn { hour } { trad } { 時 } % %<*big5> \zhnum_set_digits_map:nn { hour } { 時 } % \zhnum_set_digits_map:nn { minute } { 分 } \zhnum_set_digits_map:nn { weekday } { 星期 } \zhnum_set_financial_map:nn { null } { 零 } \zhnum_set_financial_map:nn { 0 } { 零 } \zhnum_set_financial_map:nn { 1 } { 壹 } %<*!big5> \zhnum_set_financial_map:nnn { 2 } { simp } { 贰 } \zhnum_set_financial_map:nnn { 2 } { trad } { 貳 } \zhnum_set_financial_map:nnn { 3 } { simp } { 叁 } \zhnum_set_financial_map:nnn { 3 } { trad } { 叄 } % %<*big5> \zhnum_set_financial_map:nn { 2 } { 貳 } \zhnum_set_financial_map:nn { 3 } { 參 } % \zhnum_set_financial_map:nn { 4 } { 肆 } \zhnum_set_financial_map:nn { 5 } { 伍 } %<*!big5> \zhnum_set_financial_map:nnn { 6 } { simp } { 陆 } \zhnum_set_financial_map:nnn { 6 } { trad } { 陸 } % %<*big5> \zhnum_set_financial_map:nn { 6 } { 陸 } % \zhnum_set_financial_map:nn { 7 } { 柒 } \zhnum_set_financial_map:nn { 8 } { 捌 } \zhnum_set_financial_map:nn { 9 } { 玖 } \zhnum_set_financial_map:nn { 10 } { 拾 } \zhnum_set_financial_map:nn { 100 } { 佰 } \zhnum_set_financial_map:nn { 1000 } { 仟 } \zhnum_set_tiangan_map:nn { 1 } { 甲 } \zhnum_set_tiangan_map:nn { 2 } { 乙 } \zhnum_set_tiangan_map:nn { 3 } { 丙 } \zhnum_set_tiangan_map:nn { 4 } { 丁 } \zhnum_set_tiangan_map:nn { 5 } { 戊 } \zhnum_set_tiangan_map:nn { 6 } { 己 } \zhnum_set_tiangan_map:nn { 7 } { 庚 } \zhnum_set_tiangan_map:nn { 8 } { 辛 } \zhnum_set_tiangan_map:nn { 9 } { 壬 } \zhnum_set_tiangan_map:nn { 10 } { 癸 } \zhnum_set_dizhi_map:nn { 1 } { 子 } \zhnum_set_dizhi_map:nn { 2 } { 丑 } \zhnum_set_dizhi_map:nn { 3 } { 寅 } \zhnum_set_dizhi_map:nn { 4 } { 卯 } \zhnum_set_dizhi_map:nn { 5 } { 辰 } \zhnum_set_dizhi_map:nn { 6 } { 巳 } \zhnum_set_dizhi_map:nn { 7 } { 午 } \zhnum_set_dizhi_map:nn { 8 } { 未 } \zhnum_set_dizhi_map:nn { 9 } { 申 } \zhnum_set_dizhi_map:nn { 10 } { 酉 } \zhnum_set_dizhi_map:nn { 11 } { 戌 } \zhnum_set_dizhi_map:nn { 12 } { 亥 } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \Finale % \endinput