%% %% This is file `zhnumber.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% zhnumber.dtx (with options: `package') %% %% 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. %% %% -------------------------------------------------------------------------- %% \NeedsTeXFormat{LaTeX2e} \RequirePackage{expl3} \GetIdInfo$Id: zhnumber.dtx 5e8c3fe 2022-07-14 18:53:36 +0800 Qing Lee $ {Typesetting numbers with Chinese glyphs} \ProvidesExplPackage{\ExplFileName} {\ExplFileDate}{3.0}{\ExplFileDescription} \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 } } \cs_if_exist:NF \NewDocumentCommand { \RequirePackage { xparse } } \cs_new:Npn \zhnum_output:n #1 { \exp_args:Nc \zhnum_exp_not:o { l__zhnum_ #1 _tl } } \cs_new_protected:Npn \zhnum_expand_wrap:wn #1# { \__zhnum_expand_wrap_aux:nn {#1} } \cs_new_protected:Npn \__zhnum_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 \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 } } \NewExpandableDocumentCommand \zhnumber { +o +m } { \tl_if_novalue:nTF {#1} { \zhnum_number:e } { \zhnumberwithoptions {#1} } {#2} } \NewDocumentCommand \zhnumberwithoptions { +m +m } { \group_begin: \zhnum_set:n {#1} \zhnum_number:e {#2} \group_end: } \zhnum_expand_wrap:wn \cs_new:Npn \zhnum_number:n #1 { \__zhnum_number:www #1 . \q_nil . \q_stop } \cs_new:Npn \__zhnum_number:www #1 . #2 . #3 \q_stop { \quark_if_nil:nTF {#2} { \__zhnum_integer_or_fraction:www #1 / \q_nil / \q_stop } { \zhnum_decimal:nn {#1} {#2} } } \cs_generate_variant:Nn \zhnum_number:n { e } \cs_new:Npn \__zhnum_integer_or_fraction:www #1 / #2 / #3 \q_stop { \quark_if_nil:nTF {#2} { \zhnum_integer:n {#1} } { \__zhnum_fraction:wwww #2 \q_mark #1 ; \q_nil ; \q_stop } } \cs_new:Npn \__zhnum_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} } } \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} } } \cs_new:Npn \zhnum_blank_to_zero:n #1 { \tl_if_blank:nTF {#1} { \zhnum_output:n { 0 } } { \zhnum_number:n {#1} } } \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: } \cs_new:Npn \zhnum_counter:n #1 { \int_if_exist:cTF { c@#1 } { \exp_args:Nc \zhnum_int:n { c@#1 } } { \__zhnum_counter_error:n {#1} } } \cs_new:Npn \__zhnum_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 } } } } \cs_new:Npn \@zhnum { \zhnum_int:n } \cs_new:Npn \zhnum_integer:n #1 { \exp_after:wN \__zhnum_read_integer:www \int_value:w \exp_after:wN \__zhnum_read_sign_loop:N \exp:w \exp_end_continue_f:w \use:n #1 \exp_stop_f: \q_recursion_tail \q_recursion_stop \__zhnum_result:nn { \c_zero_int } { } ; } \cs_new:Npn \__zhnum_read_sign_loop:N #1 { \if:w + \if:w - \exp_not:N #1 + \fi: \exp_not:N #1 \exp_after:wN \__zhnum_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 \__zhnum_read_zeros_loop:N \exp_after:wN #1 \fi: } \cs_new:Npn \__zhnum_read_zeros_loop:N #1 { \if:w 0 \exp_not:N #1 \exp_after:wN \__zhnum_read_zeros_loop:N \exp:w \exp_end_continue_f:w \exp_after:wN \use:n \else: \exp_after:wN \__zhnum_read_abs_loop:Nw \exp_after:wN #1 \fi: } \cs_new:Npn \__zhnum_read_abs_loop:Nw #1#2 \q_recursion_stop { \zhnum_if_digit:NTF #1 { \__zhnum_output:nnwnn { + 1 } #1 } { \quark_if_recursion_tail_stop_do:Nn #1 { \__zhnum_loop_end:wnn } } \exp_after:wN \__zhnum_read_abs_loop:Nw \exp:w \exp_end_continue_f:w \use:n #2 \q_recursion_stop } \cs_new:Npn \__zhnum_output:nnwnn #1#2#3 \__zhnum_result:nn #4#5 { #3 \__zhnum_result:nn { #4#1 } { #5#2 } } \cs_new:Npn \__zhnum_loop_end:wnn #1 \__zhnum_result:nn #2#3 { \int_eval:n {#2} ; #3 } \cs_new:Npn \__zhnum_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} } } \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: } \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 \__zhnum_parse_number:nnn { \int_mod:nn {#1} { 4 } } {#1} } \cs_new:Npn \__zhnum_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 } } } { \__zhnum_split_number_aux:nnn {#1} {#2} } } } \cs_generate_variant:Nn \zhnum_parse_number:n { f } \cs_new:Npn \__zhnum_split_number_aux:nnn #1#2 { \exp_after:wN \__zhnum_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 \__zhnum_split_number_aux:wwn #1 ; #2 ; #3 { \zhnum_split_number:nn {#1} { #2#3 } } \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 } \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 } \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} } } \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 } } { \__zhnum_counter_error:n {#1} } } \cs_new:Npn \@zhdig #1 { \zhnum_digits_null:f { \int_eval:n {#1} } } \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: } \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 } \zhnum_expand_wrap:wn \cs_new:Npn \zhnum_digits:Nn #1#2 { \exp_after:wN \__zhnum_read_digits:w \int_value:w \exp_after:wN \__zhnum_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 \__zhnum_read_sign_loop:NN #1#2 { \if:w + \if:w - \exp_not:N #2 + \fi: \exp_not:N #2 \exp_after:wN \__zhnum_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 \__zhnum_read_digits_loop:NN \exp_after:wN #1 \exp_after:wN #2 \fi: } \cs_new:Npn \__zhnum_read_digits_loop:NN #1#2 { \zhnum_if_digit:NTF #2 { \__zhnum_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 \__zhnum_read_digits_loop:NN \exp_after:wN #1 \exp:w \exp_end_continue_f:w \use:n } \cs_new:Npn \__zhnum_read_digits:w #1 ; { \int_compare:nNnF {#1} = \c_one_int { \zhnum_output:n { minus } } } \cs_new:Npn \__zhnum_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 } \NewExpandableDocumentCommand \zhdate { +s +m } { \__zhnum_date:www #2 \q_stop \bool_if:NT #1 { \__zhnum_week_day:www #2 \q_stop } } \cs_new:Npn \__zhnum_date:www #1/#2/#3 \q_stop { \__zhnum_date_aux:nnn {#1} {#2} {#3} } \cs_new:Npn \zhtoday { \__zhnum_date_aux:nnn { \int_value:w \tex_year:D } { \tex_month:D } { \tex_day:D } } \cs_new:Npn \__zhnum_date_aux:nnn { \bool_if:NTF \l__zhnum_time_bool { \__zhnum_date_aux:NNnnnn \zhnum_digits_null:n \zhnum_int:n { } } { \__zhnum_date_aux:Nnnnn \int_to_arabic:n { \l__zhnum_arabic_sep_tl } } } \cs_new:Npn \__zhnum_date_aux:Nnnnn #1#2 { \__zhnum_date_aux:NNnnnn #1#1 { \zhnum_exp_not:o {#2} } } \zhnum_expand_wrap:wn \cs_new:Npn \__zhnum_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 } } \cs_new:Npn \zhweekday #1 { \__zhnum_week_day:www #1 \q_stop } \zhnum_expand_wrap:wn \cs_new:Npn \__zhnum_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: } \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 } { \__zhnum_Zeller_aux:Nnnn \zhnum_Zeller_Gregorian:nnn } { \__zhnum_Zeller_aux:Nnnn \zhnum_Zeller_Julian:nnn } {#1} {#2} {#3} } \cs_new:Npn \__zhnum_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} } \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 } } \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 } } \zhnum_expand_wrap:wn \cs_new:Npn \zhtime #1 { \__zhnum_time:ww #1 \q_stop } \use:e { \cs_new:Npn \exp_not:N \__zhnum_time:ww #1 \c_colon_str #2 \exp_not:N \q_stop } { \__zhnum_time_aux:nn {#1} {#2} } \zhnum_expand_wrap:wn \cs_new:Npn \zhcurrtime { \__zhnum_time_aux:nn { \int_div_truncate:nn \tex_time:D { 60 } } { \int_mod:nn \tex_time:D { 60 } } } \cs_new:Npn \__zhnum_time_aux:nn { \bool_if:NTF \l__zhnum_time_bool { \__zhnum_time_aux:Nnnn \zhnum_int:n { } } { \__zhnum_time_aux:Nnnn \int_to_arabic:n { \l__zhnum_arabic_sep_tl } } } \cs_new:Npn \__zhnum_time_aux:Nnnn #1#2#3#4 { #1 {#3} #2 \zhnum_output:n { hour } #2 #1 {#4} #2 \zhnum_output:n { minute } } \cs_new:Npn \zhnum_scale_map:n #1 { \tl_if_exist:cTF { l__zhnum_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__zhnum_scale_int } } \cs_generate_variant:Nn \zhnum_scale_map:n { f } \int_new:N \l__zhnum_scale_int \int_set:Nn \l__zhnum_scale_int { 11 } \cs_new_eq:NN \zhnum_scale_map_hook:n \zhnum_scale_map_loop:n \tl_new:c { l__zhnum_s 0 _tl } \NewDocumentCommand \zhnumExtendScaleMap { > { \TrimSpaces } +o +m } { \int_zero:N \l__zhnum_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} } } \cs_new_protected:Npn \zhnum_set_scale:n #1 { \int_incr:N \l__zhnum_tmp_int \exp_args:Nc \__zhnum_set_scale:Nn { l__zhnum_s \int_eval:n { \l__zhnum_tmp_int + 11 } _tl } {#1} } \cs_new_protected:Npn \__zhnum_set_scale:Nn #1 { \tl_if_exist:NF #1 { \tl_new:N #1 \int_incr:N \l__zhnum_scale_int } \tl_set:Nn #1 } \int_new:N \l__zhnum_tmp_int \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__zhnum_ #2 _ #1 _tl } { \zhnum_output:n { #2 _ #1 } } } } \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__zhnum_ #2 _ #1 _tl } { \zhnum_output:n { #2 _ #1 } } { \__zhnum_ganzhi_cyclic_mod:fnnn { \int_mod:nn {#1} {#3} } {#1} {#2} {#3} } } } \cs_new:Npn \__zhnum_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 \__zhnum_ganzhi_cyclic_mod:nnnn { f } \cs_new_eq:NN \zhnum_ganzhi:nnn \zhnum_ganzhi_normal:nnn \cs_generate_variant:Nn \zhnum_ganzhi:nnn { f } \cs_new:Npn \zhtiangan #1 { \zhnum_ganzhi:fnn { \int_eval:n {#1} } { tiangan } { 10 } } \cs_new:Npn \zhdizhi #1 { \zhnum_ganzhi:fnn { \int_eval:n {#1} } { dizhi } { 12 } } \cs_new:Npn \zhganzhi #1 { \zhnum_ganzhi:fnn { \int_eval:n {#1} } { ganzhi } { 60 } } \cs_new:Npn \zhganzhinian #1 { \zhnum_ganzhi_nian:f { \int_eval:n {#1} } } \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 } \tl_new:N \l__zhnum_kv_tl \tl_new:N \l__zhnum_tmp_tl \group_begin: \tl_build_begin:N \l__zhnum_kv_tl \int_step_inline:nn { 10 } { \tl_new:c { l__zhnum_ #1 _tl } \tl_build_put_right:Nx \l__zhnum_kv_tl { #1 .tl_set:N = \exp_not:c { l__zhnum_normal_ #1 _tl } , F#1 .tl_set:N = \exp_not:c { l__zhnum_financial_ #1 _tl } , E \int_eval:n { #1 * 4 } .tl_set:N = \exp_not:c { l__zhnum_ s#1 _tl } , } } \clist_map_inline:nn { 0 , 100 , 1000 } { \tl_new:c { l__zhnum_ #1 _tl } \tl_build_put_right:Nx \l__zhnum_kv_tl { #1 .tl_set:N = \exp_not:c { l__zhnum_normal_ #1 _tl } , F#1 .tl_set:N = \exp_not:c { l__zhnum_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__zhnum_kv_tl { #1 .tl_set:N = \exp_not:c { l__zhnum_ #1 _tl } , } } \tl_build_put_right:Nx \l__zhnum_kv_tl { - .tl_set:N = \exp_not:N \l__zhnum_minus_tl , -0 .tl_set:N = \exp_not:N \l__zhnum_null_tl , E2 .tl_set:N = \exp_not:c { l__zhnum_normal_ 100 _tl } , E3 .tl_set:N = \exp_not:c { l__zhnum_normal_ 1000 _tl } , FE2 .tl_set:N = \exp_not:c { l__zhnum_financial_ 100 _tl } , FE3 .tl_set:N = \exp_not:c { l__zhnum_financial_ 1000 _tl } , E44 .tl_set:N = \exp_not:c { l__zhnum_ s11 _tl } } \tl_build_get:NN \l__zhnum_kv_tl \l__zhnum_tmp_tl \cs_set:Npn \__zhnum_tmp:w #1 . #2 \q_stop { , #1 .groups:n = { user } } \clist_map_inline:Nn \l__zhnum_tmp_tl { \tl_build_put_right:Nx \l__zhnum_kv_tl { \__zhnum_tmp:w #1 \q_stop } } \tl_build_put_right:Nn \l__zhnum_kv_tl { , weekday .tl_set:N = \l__zhnum_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__zhnum_kv_tl { #1 .tl_set:N = \exp_not:c { l__zhnum_ #1 _tl } , #1 .groups:n = { user , pos , day } , } } \int_step_inline:nn { 10 } { \tl_build_put_right:Nx \l__zhnum_kv_tl { T#1 .tl_set:N = \exp_not:c { l__zhnum_ganzhi_ #1 _tl } , T#1 .groups:n = { user , pre , tiandi } , } } \int_step_inline:nn { 12 } { \tl_build_put_right:Nx \l__zhnum_kv_tl { D#1 .tl_set:N = \exp_not:c { l__zhnum_dizhi_ #1 _tl } , D#1 .groups:n = { user , pre , tiandi } , } } \int_step_inline:nn { 60 } { \tl_build_put_right:Nx \l__zhnum_kv_tl { GZ#1 .tl_set:N = \exp_not:c { l__zhnum_ganzhi_ #1 _tl } , GZ#1 .groups:n = { user , pos , ganzhi } , } } \tl_build_end:N \l__zhnum_kv_tl \exp_args:NNno \group_end: \keys_define:nn { zhnum / options } { \l__zhnum_kv_tl } \cs_new_protected:Npn \zhnum_set_digits_map:nn #1 { \prop_put:Nnn \l__zhnum_cfg_map_prop {#1} } \cs_new_protected:Npn \zhnum_set_digits_map:nnn #1#2#3 { \prop_put_if_new:Nnn \l__zhnum_cfg_map_prop {#1} {#3} \prop_put:Nnn \l__zhnum_cfg_map_var_prop {#1_#2} {#3} } \cs_new_protected:Npn \zhnum_set_financial_map:nn #1 { \prop_put:Nnn \l__zhnum_cfg_map_finan_prop {#1} } \cs_new_protected:Npn \zhnum_set_financial_map:nnn #1#2#3 { \prop_put_if_new:Nnn \l__zhnum_cfg_map_finan_prop {#1} {#3} \prop_put:Nnn \l__zhnum_cfg_map_var_prop { financial_#1_#2 } {#3} } \cs_new_protected:Npn \zhnum_set_tiangan_map:nn #1 { \prop_put:Nnn \l__zhnum_cfg_map_ganzhi_prop { tiangan_#1 } } \cs_new_protected:Npn \zhnum_set_dizhi_map:nn #1 { \prop_put:Nnn \l__zhnum_cfg_map_ganzhi_prop { dizhi_#1 } } \prop_new:N \l__zhnum_cfg_map_prop \prop_new:N \l__zhnum_cfg_map_var_prop \prop_new:N \l__zhnum_cfg_map_finan_prop \prop_new:N \l__zhnum_cfg_map_ganzhi_prop \cs_new_protected:Npn \zhnum_parse_config: { \tl_clear_new:N \l__zhnum_reset_tl \tl_clear_new:N \l__zhnum_reset_simp_tl \tl_clear_new:N \l__zhnum_reset_trad_tl \tl_clear_new:N \l__zhnum_set_ancient_tl \tl_clear_new:N \l__zhnum_set_normal_tl \tl_clear_new:N \l__zhnum_reset_ancient_tl \tl_clear_new:N \l__zhnum_reset_normal_tl \tl_clear_new:N \l__zhnum_reset_financial_tl \prop_map_function:NN \l__zhnum_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__zhnum_cfg_map_var_prop { #1_ancient } \l__zhnum_ancient_tl { \__zhnum_add_reset_ancient:nN {#1} \l__zhnum_ancient_tl } { \__zhnum_check_simp_aux:nn {#2} {#1} \prop_get:NnNT \l__zhnum_cfg_map_finan_prop {#1} \l__zhnum_tmp_tl { \exp_args:No \__zhnum_check_simp_aux:nn { \l__zhnum_tmp_tl } { financial_ #1 } \__zhnum_add_reset_financial:n {#1} } } } \cs_new_protected:Npn \__zhnum_check_simp_aux:nn #1#2 { \prop_get:NnNTF \l__zhnum_cfg_map_var_prop { #2 _trad } \l__zhnum_trad_tl { \prop_get:NnNF \l__zhnum_cfg_map_var_prop { #2 _simp } \l__zhnum_simp_tl { \tl_set:Nn \l__zhnum_simp_tl {#1} } \__zhnum_add_reset_simp:nNN {#2} \l__zhnum_simp_tl \l__zhnum_trad_tl } { \__zhnum_add_reset:nn {#2} {#1} } } \tl_new:N \l__zhnum_simp_tl \tl_new:N \l__zhnum_trad_tl \tl_new:N \l__zhnum_ancient_tl \cs_new_protected:Npn \__zhnum_add_reset:nn #1#2 { \tl_put_right:Nx \l__zhnum_reset_tl { \tl_set:Nn \exp_not:c { l__zhnum_ #1 _tl } { \exp_not:n {#2} } } } \cs_new_protected:Npn \__zhnum_add_reset_simp:nNN #1#2#3 { \tl_put_right:Nx \l__zhnum_reset_simp_tl { \tl_set:Nn \exp_not:c { l__zhnum_ #1 _tl } { \exp_not:o {#2} } } \tl_put_right:Nx \l__zhnum_reset_trad_tl { \tl_set:Nn \exp_not:c { l__zhnum_ #1 _tl } { \exp_not:o {#3} } } } \cs_new_protected:Npn \__zhnum_add_reset_financial:n #1 { \tl_put_right:Nx \l__zhnum_set_normal_tl { \tl_set_eq:NN \exp_not:c { l__zhnum_normal_ #1 _tl } \exp_not:c { l__zhnum_ #1 _tl } } \tl_put_right:Nx \l__zhnum_reset_normal_tl { \tl_set_eq:NN \exp_not:c { l__zhnum_ #1 _tl } \exp_not:c { l__zhnum_normal_ #1 _tl } } \tl_put_right:Nx \l__zhnum_reset_financial_tl { \tl_set_eq:NN \exp_not:c { l__zhnum_ #1 _tl } \exp_not:c { l__zhnum_financial_ #1 _tl } } } \cs_new_protected:Npn \__zhnum_add_reset_ancient:nN #1#2 { \tl_put_right:Nx \l__zhnum_reset_ancient_tl { \tl_set:Nn \exp_not:c { l__zhnum_ #1 _tl } { \exp_not:o {#2} } } \tl_put_right:Nx \l__zhnum_set_ancient_tl { \tl_concat:NNN \exp_not:c { l__zhnum_ #1 _tl } \exp_not:c { l__zhnum_ \str_head:n {#1} _tl } \exp_not:c { l__zhnum_ 1 \str_tail:n {#1} _tl } } } \cs_new_protected:Npn \zhnum_set_week_day: { \cs_set_protected:Npx \zhnum_reset_week_day: { \__zhnum_set_week_day:nn { mon } { 1 } \__zhnum_set_week_day:nn { tue } { 2 } \__zhnum_set_week_day:nn { wed } { 3 } \__zhnum_set_week_day:nn { thu } { 4 } \__zhnum_set_week_day:nn { fri } { 5 } \__zhnum_set_week_day:nn { sat } { 6 } \__zhnum_set_week_day:nn { sun } { day } } } \cs_new_eq:NN \zhnum_reset_week_day: \prg_do_nothing: \cs_new:Npn \__zhnum_set_week_day:nn #1#2 { \tl_set:Nx \exp_not:c { l__zhnum_ #1 _tl } { \exp_not:N \exp_not:o { \exp_not:N \l__zhnum_weekday_tl } \exp_not:N \exp_not:n { \exp_not:v { l__zhnum_ #2 _tl } } } } \cs_new_protected:Npn \zhnum_set_ganzhi: { \prop_map_function:NN \l__zhnum_cfg_map_ganzhi_prop \__zhnum_add_reset:nn } \cs_new_protected:Npn \__zhnum_reset_ganzhi:nn #1#2 { \tl_set:cn { l__zhnum_ #1 _tl } {#2} } \cs_new:Npn \zhnum_zero_mod:nn #1#2 { \exp_args:Nf \__zhnum_zero_mod_aux:nn { \int_mod:nn {#1} {#2} } {#2} } \cs_new:Npn \__zhnum_zero_mod_aux:nn #1#2 { \int_compare:nNnTF {#1} = \c_zero_int {#2} {#1} } \tl_new:c { l__zhnum_dizhi_ 0 _tl } \tl_new:c { l__zhnum_ganzhi_ 0 _tl } \tl_new:c { l__zhnum_tiangan_ 0 _tl } \group_begin: \cs_set:Npn \__zhnum_tmp:w #1 { \tl_concat:NNN \exp_not:c { l__zhnum_ganzhi_ #1 _tl } \exp_not:c { l__zhnum_tiangan_ \zhnum_zero_mod:nn {#1} { 10 } _tl } \exp_not:c { l__zhnum_dizhi_ \zhnum_zero_mod:nn {#1} { 12 } _tl } } \cs_new_protected:Npx \zhnum_reset_ganzhi: { \tl_set_eq:NN \exp_not:c { l__zhnum_dizhi_ 0 _tl } \exp_not:c { l__zhnum_dizhi_ 12 _tl } \tl_set_eq:NN \exp_not:c { l__zhnum_tiangan_ 0 _tl } \exp_not:c { l__zhnum_tiangan_ 10 _tl } \int_step_function:nN { 60 } \__zhnum_tmp:w \tl_set_eq:NN \exp_not:c { l__zhnum_ganzhi_ 0 _tl } \exp_not:c { l__zhnum_ganzhi_ 60 _tl } } \group_end: \cs_new_protected:Npn \zhnum_reset_config: { \zhnum_load_cfg:o { \l__zhnum_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__zhnum_reset_tl \tl_use:N \l__zhnum_set_normal_tl \tl_concat:NNN \l__zhnum_reset_normal_tl \l__zhnum_reset_normal_tl \c__zhnum_set_zero_tl \tl_concat:NNN \l__zhnum_reset_financial_tl \l__zhnum_reset_financial_tl \c__zhnum_set_zero_tl \tl_concat:NNN \l__zhnum_reset_financial_tl \l__zhnum_reset_financial_tl \l__zhnum_set_ancient_tl } \tl_const:Nx \c__zhnum_set_zero_tl { \tl_set_eq:NN \exp_not:N \l__zhnum_zero_tl \exp_not:c { l__zhnum_0_tl } } \tl_new:N \l__zhnum_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__zhnum_simp_bool { \tl_use:N \l__zhnum_reset_simp_tl } { \tl_use:N \l__zhnum_reset_trad_tl } } \cs_new_protected:Npn \zhnum_reset_normal: { \bool_if:NTF \l__zhnum_normal_bool { \tl_use:N \l__zhnum_reset_normal_tl \__zhnum_reset_ancient: \__zhnum_reset_zero: } { \tl_use:N \l__zhnum_reset_financial_tl } } \cs_new_protected:Npn \__zhnum_reset_ancient: { \bool_if:NTF \l__zhnum_ancient_bool { \tl_use:N \l__zhnum_reset_ancient_tl } { \tl_use:N \l__zhnum_set_ancient_tl } } \cs_new_protected:Npx \__zhnum_reset_zero: { \exp_not:n { \bool_if:NT \l__zhnum_null_bool } { \tl_set_eq:NN \exp_not:c { l__zhnum_0_tl } \exp_not:N \l__zhnum_null_tl } } \cs_new_protected:Npn \zhnum_load_cfg:n #1 { \zhnum_set_cfg_name:Nn \l__zhnum_cfg_str {#1} \str_if_eq:NNTF \l__zhnum_cfg_str \l__zhnum_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__zhnum_cfg_ \l__zhnum_cfg_str _prop } { \__zhnum_set_cfg_prop: } { \zhnum_input_cfg:n {#1} } } \cs_new_protected:Npn \__zhnum_set_cfg_prop: { \str_set_eq:NN \l__zhnum_last_cfg_str \l__zhnum_cfg_str \__zhnum_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__zhnum_cfg_file_tl { \bool_set_false:N \l__zhnum_reset_bool \__zhnum_update_cfg_prop:N \__zhnum_prop_initial:Nn \group_begin: \zhnum_set_catcode: \exp_args:No \file_input:n { \l__zhnum_cfg_file_tl } \__zhnum_update_cfg_prop:N \__zhnum_prop_gset_eq:Nn \group_end: \__zhnum_set_cfg_prop: } { \msg_error:nnx { zhnumber } { file-not-found } {#1} } } \tl_new:N \l__zhnum_cfg_file_tl \cs_new_protected:Npn \__zhnum_update_cfg_prop:N { \exp_args:No \__zhnum_update_cfg_prop_aux:nN { \l__zhnum_cfg_str } } \cs_new_protected:Npn \__zhnum_update_cfg_prop_aux:nN #1#2 { #2 \l__zhnum_cfg_map_prop { g__zhnum_cfg_ #1 _prop } #2 \l__zhnum_cfg_map_var_prop { g__zhnum_cfg_var_ #1 _prop } #2 \l__zhnum_cfg_map_finan_prop { g__zhnum_cfg_finan_ #1 _prop } #2 \l__zhnum_cfg_map_ganzhi_prop { g__zhnum_cfg_ganzhi_ #1 _prop } } \cs_new_protected:Npn \__zhnum_prop_initial:Nn #1#2 { \prop_clear:N #1 \prop_new:c {#2} } \cs_new_protected:Npn \__zhnum_prop_gset_eq:Nn #1#2 { \prop_gset_eq:cN {#2} #1 } \str_new:N \l__zhnum_cfg_str \str_new:N \l__zhnum_last_cfg_str \bool_new:N \l__zhnum_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. } \bool_const:Nn \c__zhnum_unicode_engine_bool { \bool_lazy_any_p:n { { \sys_if_engine_xetex_p: } { \sys_if_engine_luatex_p: } { \sys_if_engine_uptex_p: } } } \bool_if:NTF \c__zhnum_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__zhnum_encoding_str {#2} \str_set_eq:NN #1 \l__zhnum_encoding_str } } { \cs_new_protected:Npn \zhnum_set_catcode: { \bool_if:NTF \l__zhnum_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__zhnum_encoding_str {#2} \str_set:Nx #1 { \l__zhnum_encoding_str \bool_if:NTF \l__zhnum_active_char_bool { / active } { / other } } } \bool_new:N \l__zhnum_active_char_bool \bool_set_true:N \l__zhnum_active_char_bool } \cs_new_protected:Npn \zhnum_set_encoding:n #1 { \str_set:Nx \l__zhnum_encoding_str { \str_lowercase:n {#1} } \zhnum_load_cfg:o { \l__zhnum_encoding_str } } \str_new:N \l__zhnum_encoding_str \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__zhnum_ancient_bool \bool_set_true:N \l__zhnum_normal_bool } , style / Financial .code:n = { \bool_set_false:N \l__zhnum_ancient_bool \bool_set_false:N \l__zhnum_normal_bool } , style / Ancient .code:n = { \bool_set_true:N \l__zhnum_ancient_bool \bool_set_true:N \l__zhnum_normal_bool } , style / Simplified .code:n = { \bool_set_true:N \l__zhnum_simp_bool } , style / Traditional .code:n = { \bool_set_false:N \l__zhnum_simp_bool } , style .default:n = { Normal , Simplified } , style .groups:n = { style } , null .bool_set:N = \l__zhnum_null_bool , null .groups:n = { style } , time .choice: , time / Chinese .code:n = { \bool_set_true:N \l__zhnum_time_bool } , time / Arabic .code:n = { \bool_set_false:N \l__zhnum_time_bool } , time .default:n = { Arabic } , reset .bool_set:N = \l__zhnum_reset_bool , activechar .bool_set:N = \l__zhnum_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__zhnum_arabic_sep_tl } \bool_new:N \l__zhnum_simp_bool \bool_new:N \l__zhnum_normal_bool \bool_new:N \l__zhnum_ancient_bool \msg_new:nnnn { zhnumber } { encoding-invalid } { The~encoding~`#1'~is~invalid. } { Available~encodings~are~`UTF8',~`GBK'~and~`Big5'. } \NewDocumentCommand \zhnumsetup { +m } { \zhnum_set:n {#1} \tex_ignorespaces:D } \cs_new_protected:Npn \zhnum_set:n #1 { \bool_set_false:N \l__zhnum_reset_bool \keys_set_filter:nnnN { zhnum / options } { style , user } {#1} \l__zhnum_kv_tl \tl_if_empty:NF \l__zhnum_kv_tl { \__zhnum_set_style: } \bool_if:NT \l__zhnum_reset_bool { \zhnum_reset_config: } } \cs_new_protected:Npn \__zhnum_set_style: { \keys_set_filter:nnoN { zhnum / options } { user } { \l__zhnum_kv_tl } \l__zhnum_tmp_tl \tl_if_empty:NTF \l__zhnum_tmp_tl { \zhnum_reset_style: } { \tl_if_eq:NNF \l__zhnum_tmp_tl \l__zhnum_kv_tl { \zhnum_reset_style: } \bool_if:NF \l__zhnum_reset_bool { \__zhnum_set_user: } } } \cs_new_protected:Npn \__zhnum_set_user: { \keys_set_filter:nnoN { zhnum / options } { pre , pos } { \l__zhnum_tmp_tl } \l__zhnum_kv_tl \tl_if_eq:NNF \l__zhnum_kv_tl \l__zhnum_tmp_tl { \zhnum_reset_normal: } \tl_if_empty:NF \l__zhnum_kv_tl { \__zhnum_set_pre_pos: } } \cs_new_protected:Npn \__zhnum_set_pre_pos: { \keys_set_filter:nnoN { zhnum / options } { pos } { \l__zhnum_kv_tl } \l__zhnum_tmp_tl \tl_if_eq:NNF \l__zhnum_tmp_tl \l__zhnum_kv_tl { \zhnum_reset_week_day: \zhnum_reset_ganzhi: } \tl_if_empty:NF \l__zhnum_kv_tl { \keys_set:no { zhnum / options } { \l__zhnum_kv_tl } } } \cs_generate_variant:Nn \keys_set_filter:nnnN { nno } \keys_set:nn { zhnum / options } { style , time , arabicsep = { ~ } } \cs_if_exist:NTF \ProcessKeyOptions { \ProcessKeyOptions [ zhnum / options ] } { \RequirePackage { l3keys2e } \ProcessKeysOptions { zhnum / options } } \str_if_empty:NTF \l__zhnum_encoding_str { \zhnum_set_encoding:n { UTF8 } } { \zhnum_reset_style: } %% %% 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. %% %% End of file `zhnumber.sty'.