使用日期和月份代替页码

使用日期和月份代替页码

我正在用 LaTeX 写一本 365 页的个人一年日记。我将使用日+月作为页码,而不是数字,因此:

  • 首页页码不是1,而是1 Jan...

  • 第 32 页不是 32,而是 2 月 1 日……

  • 最后一个不是 365/366,而是 12 月 31 日......

等等。我该怎么做?

答案1

可能不是最理想的,但是...

使用expl3:)

代码略加注释以解释其本身。基本上,我们使用\SetupDiary创建每个月天数的列表。您可以使用\SetupDiary[<year>]指定年份。如果未提供可选参数,则默认为\year

之后,\SetupDiary您可以使用 将日期转换为日期\SeqToDate{<day>}。在示例中,我使用 对日期进行页码编号\def\thepage{\SeqToDate{\value{page}}}

注意!如果给定年份中不存在该日期,则会引发错误。例如,\SetupYear[2018]\SeqToDate{366}不起作用。确保在日期部分完成后取消定义页码。

随机一页:)

在此处输入图片描述

\documentclass{article}

\usepackage[a6paper]{geometry}

\usepackage{xparse}
\usepackage{pgffor}% Just for printing many pages
\usepackage{lipsum}% Dummy text
\usepackage[super]{nth}% For ordinal printing

\ExplSyntaxOn
% First we create an auxiliary command that checks if the year is a leap year
% \leapyear{<year>}
% Expands to 1 if February has 29 days
% Takes into account the 4-year rule, the 100-year exception, and the 400-year 
\NewExpandableDocumentCommand\leapyear
  { m }
  {
    \fp_eval:n {
      (
         \int_mod:nn { #1 } {  4  }  = 0 % 4-year rule
       &&
         \int_mod:nn { #1 } { 100 } != 0 % 100-year exception
      )
      || \int_mod:nn { #1 } { 400 }  = 0 % 400-year meta-exception
    }
  }
% A few variables
\seq_new:N \moz_eomday
\seq_new:N \moz_eomsum
\seq_new:N \moz_months
% Now we create a \seq list with the month names
\seq_set_from_clist:Nn \moz_months
  { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dez }
% Create a function that generates the number of days per month taking \leapyear into account
\cs_new:Npn \moz_make_eomday:n #1 {
  \seq_set_from_clist:Nn \moz_eomday
    { 0, 31, \int_eval:n {28 + \leapyear {#1} }, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
}
% A recursive function that creates a cumulative sum of the number of days
\cs_new:Npn \moz_make_eomsum: {
  \seq_pop_left:NNTF \moz_eomday \l_tmpa_tl
  {
    \int_set:Nn \l_tmpa_int { \l_tmpa_tl + \l_tmpa_int }
    \seq_put_right:Nx \moz_eomsum { \int_use:N \l_tmpa_int }
    \moz_make_eomsum:
  }
  { }
}
% Now the main thing begins.
% First, a function that generates the number-of-days list
% \SetupDiary[<year>]
% Doesn't produce output
% The optional argument is the year to be used. If none is given, defaults to \year
\NewDocumentCommand\SetupDiary
  { O { \year } }
  {
    \moz_make_eomday:n { #1 }
    \int_zero:N \l_tmpa_int
    \seq_clear:N \moz_eomsum
    \moz_make_eomsum:
  }
% And the main function that takes the sequential day and converts to day and month
% \SeqToDate{<sequential-day>}[\<output-function>]
% Converts <sequential-day> to <dom> and <month> then calls \<output-function> {<dom>}{<month>}
\NewDocumentCommand\SeqToDate
  { m O { \moz_print_date:nn } }
  {
    \seq_get_right:NN \moz_eomsum \l_tmpa_tl
    \int_compare:nNnT
      { \int_eval:n { #1 } }
       >
      { \l_tmpa_tl }
      { \msg_fatal:nn { SeqToDate } { Day~\int_eval:n { #1 }~too~big.~Max~=~\tl_use:N \l_tmpa_tl. } }
    \int_zero:N \l_tmpa_int
    \int_do_while:nNnn
      { \int_eval:n { #1 } }
       >
      { \seq_item:Nn \moz_eomsum { \l_tmpa_int + 1 } }
      { \int_incr:N \l_tmpa_int }
    \int_set:Nn \l_tmpb_int { #1 - \seq_item:Nn \moz_eomsum { \l_tmpa_int } }
    #2 { \int_use:N \l_tmpb_int } { \seq_item:Nn \moz_months { \l_tmpa_int } }
  }
% This function takes the <dom> and <month> as arguments and prints them as <dom>~<month>
\cs_new:Npn \moz_print_date:nn #1 #2 {
  #1~#2
}
% This function takes the <dom> and <month> as arguments and prints them as <month>,~<dom>th
\cs_new:Npn \printordinal #1 #2 {
  #2,~\nth{ #1 }
}
\ExplSyntaxOff

% Test document
\begin{document}

% Setup first to create the number-of-days list
\SetupDiary

% Make the page number be the date
\def\thepage{\SeqToDate{\value{page}}}

% Prints lots of pages :)
\foreach \i in {1,...,365}{%
  \section*{\SeqToDate{\i}[\printordinal]}%
  \lipsum[4]\clearpage
  }

% CAREFUL! One more page will throw an error!
% Make the page numbering sequential again
\def\thepage{\value{page}}

\end{document}

相关内容