我写了一些代码来查找复活节的日期。现在我想用它和 TiKZ 日历来标记与复活节相关的节日。
以下是我目前所掌握的信息:
\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage{libertine}
\usepackage[margin=5pt,a5paper,landscape]{geometry}
\setlength{\parindent}{0pt}
\usepackage{tikz}
\usetikzlibrary{calendar}
\usepackage{expl3}
\ExplSyntaxOn
%% Knuth's AoCP, vol 1, 2nd ed, pp 155--156
\int_new:N \l_easter_Y_int
\int_new:N \l_easter_G_int
\int_new:N \l_easter_C_int
\int_new:N \l_easter_X_int
\int_new:N \l_easter_Z_int
\int_new:N \l_easter_D_int
\int_new:N \l_easter_E_int
\int_new:N \l_easter_N_int
\int_new:N \l_easter_M_int
\cs_new:Nn \easter_sunday:n {
\int_set:Nn \l_easter_Y_int { #1 }
\int_set:Nn \l_easter_G_int {
\int_mod:nn { \l_easter_Y_int } { 19 } + 1
}
\int_set:Nn \l_easter_C_int {
\int_div_truncate:nn { \l_easter_Y_int } { 100 } + 1
}
\int_set:Nn \l_easter_X_int {
\int_div_truncate:nn { 3 * \l_easter_C_int } { 4 } - 12
}
\int_set:Nn \l_easter_Z_int {
\int_div_truncate:nn { 8 * \l_easter_C_int + 5 } { 25 } - 5
}
\int_set:Nn \l_easter_D_int {
\int_div_truncate:nn { 5 * \l_easter_Y_int } { 4 } - \l_easter_X_int - 10
}
\int_set:Nn \l_easter_E_int {
\int_mod:nn { 11 * \l_easter_G_int + 20 + \l_easter_Z_int
- \l_easter_X_int } { 30 }
}
% \int_mod:nn behaves strangely.
\int_compare:nNnT { \l_easter_E_int } < { 0 }
{
\int_add:Nn \l_easter_E_int { 30 }
}
\int_compare:nNnTF { \l_easter_E_int } = { 25 }
{ % true
\int_compare:nNnT { \l_easter_G_int } > { 11 }
{ % true
\int_incr:N \l_easter_E_int
}
}
{ % false
\int_compare:nNnT { \l_easter_E_int } = { 24 }
{ % true
\int_incr:N \l_easter_E_int
}
}
\int_set:Nn \l_easter_N_int { 44 - \l_easter_E_int }
\int_compare:nNnT { \l_easter_N_int } < { 21 }
{ % true
\int_add:Nn \l_easter_N_int { 30 }
}
\int_add:Nn \l_easter_N_int {
7 - \int_mod:nn { \l_easter_D_int + \l_easter_N_int } { 7 }
}
\int_compare:nNnTF { \l_easter_N_int } > { 31 }
{ % true
\int_sub:Nn \l_easter_N_int { 31 }
\int_set:Nn \l_easter_M_int { 4 } % April
}
{ % false
\int_set:Nn \l_easter_M_int { 3 } % March
}
}
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\calendar[dates=2012-04-01 to 2012-05-last, week list];
\end{tikzpicture}
\end{document}
答案1
诀窍是使用命令\pgfkeys
。
完整代码如下:
\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage{libertine}
\usepackage[margin=5pt,a5paper,landscape]{geometry}
\setlength{\parindent}{0pt}
\usepackage{tikz}
\usetikzlibrary{calendar}
\usepackage{expl3}
\ExplSyntaxOn
%% Knuth's AoCP, vol 1, 2nd ed, pp 155--156
\int_new:N \l_easter_Y_int
\int_new:N \l_easter_G_int
\int_new:N \l_easter_C_int
\int_new:N \l_easter_X_int
\int_new:N \l_easter_Z_int
\int_new:N \l_easter_D_int
\int_new:N \l_easter_E_int
\int_new:N \l_easter_N_int
\int_new:N \l_easter_M_int
\int_new:N \l_easter_julian_day_int
\cs_new:Nn \easter_sunday:n {
\int_set:Nn \l_easter_Y_int { #1 }
\int_set:Nn \l_easter_G_int {
\int_mod:nn { \l_easter_Y_int } { 19 } + 1
}
\int_set:Nn \l_easter_C_int {
\int_div_truncate:nn { \l_easter_Y_int } { 100 } + 1
}
\int_set:Nn \l_easter_X_int {
\int_div_truncate:nn { 3 * \l_easter_C_int } { 4 } - 12
}
\int_set:Nn \l_easter_Z_int {
\int_div_truncate:nn { 8 * \l_easter_C_int + 5 } { 25 } - 5
}
\int_set:Nn \l_easter_D_int {
\int_div_truncate:nn { 5 * \l_easter_Y_int } { 4 } - \l_easter_X_int - 10
}
\int_set:Nn \l_easter_E_int {
\int_mod:nn { 11 * \l_easter_G_int + 20 + \l_easter_Z_int
- \l_easter_X_int } { 30 }
}
% \int_mod:nn behaves strangely.
\int_compare:nNnT { \l_easter_E_int } < { 0 }
{
\int_add:Nn \l_easter_E_int { 30 }
}
\int_compare:nNnTF { \l_easter_E_int } = { 25 }
{ % true
\int_compare:nNnT { \l_easter_G_int } > { 11 }
{ % true
\int_incr:N \l_easter_E_int
}
}
{ % false
\int_compare:nNnT { \l_easter_E_int } = { 24 }
{ % true
\int_incr:N \l_easter_E_int
}
}
\int_set:Nn \l_easter_N_int { 44 - \l_easter_E_int }
\int_compare:nNnT { \l_easter_N_int } < { 21 }
{ % true
\int_add:Nn \l_easter_N_int { 30 }
}
\int_add:Nn \l_easter_N_int {
7 - \int_mod:nn { \l_easter_D_int + \l_easter_N_int } { 7 }
}
\int_compare:nNnTF { \l_easter_N_int } > { 31 }
{ % true
\int_sub:Nn \l_easter_N_int { 31 }
\int_set:Nn \l_easter_M_int { 4 } % April
}
{ % false
\int_set:Nn \l_easter_M_int { 3 } % March
}
\pgfcalendardatetojulian { \l_easter_Y_int -
\l_easter_M_int - \l_easter_N_int
} { \l_easter_julian_day_int }
}
\pgfkeys{/pgf/calendar/Easter/.default = 0}
\pgfkeys{/pgf/calendar/Easter/.code =
{
\easter_sunday:n { \pgfcalendarifdateyear }
\int_compare:nNnT { \pgfcalendarifdatejulian }
= {\l_easter_julian_day_int + #1}
{ \pgfcalendarmatchestrue }
}
}
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\calendar[dates=2012-04-01 to 2012-05-last, week list]
if (Easter=-3, % Maundy Thursday
Easter=-2, % Good Friday
Easter, % Easter Sunday
Easter=1, % Easter Monday
Easter=39, % Feast of the Ascension
Easter=49, % Pentecost
Easter=50) % Whit Monday
[red];
\end{tikzpicture}
\end{document}
结果如下:
以下是扩展版本:http://pastebin.com/KYngbPGQ
这里还有一个版本:http://www.texample.net/tikz/examples/birthday-calendar/
请注意,此解决方案需要最新的 TeX 发行版。它不适用于 Ubuntu 12.04 及更早版本附带的发行版。
答案2
相同的代码,但使用 TeX 计数。
公式来自WikiBooks:算法汇编:日历:节日被使用。
由于测试的性质,如果使用参数Easter
(例如Eastern=365
),使得要测试的实际日期不在当前年份,则测试将失败。(您无法测试 2013 年中相对于 2012 年东部的某一天。)
代码
\documentclass[tikz]{standalone}
\usetikzlibrary{calendar}
\makeatletter
\def\pgfcalendar@Easter#1{%
\begingroup
\count0=#1\relax % Yeah 0
\count1=\count0% % K 1
\divide\count1 100 % K 1
\count2=\count1 % M 3
\multiply\count2 3
\advance\count2 3
\divide\count2 4 % 2 holds (3 * K +3) \ 4
\count3=\count1
\multiply\count3 8
\advance\count3 13
\divide\count3 -25
\advance\count3\count2
\advance\count3 15 % M 3
\count2-\count2 % S 2
\advance\count2 2
\count4=\count0 % A 4
\divide\count4 19
\multiply\count4 -19
\advance\count4\count0 % A 4
\count1=\count4 % D 1 *
\multiply\count1 19
\advance\count1\count3
\count5\count1
\divide\count1 30
\multiply\count1 -30
\advance\count1\count5 % D 1 *
\divide\count4 11 % R 4 *
\advance\count4\count1
\divide\count4 29 % R 4 *
\advance\count1-\count4 % OG 1 **
\advance\count1 21 % OG 1 **
\count3\count0 % SZ 3 *
\divide\count3 4
\advance\count3\count0
\advance\count3\count2
\count4-\count3
\divide\count3 7
\multiply\count3 7
\advance\count3\count4
\advance\count3 7 % SZ 3 *
\count4-\count3 % OE 4 **
\advance\count4\count1
\count3-\count4
\divide\count4 7
\multiply\count4 7
\advance\count4\count3
\advance\count4 7 % OE 4 **
\advance\count4\count1
\pgfcalendardatetojulian{\the\count0-03-\the\count4}\pgfutil@tempcnta
\expandafter\xdef\csname pgfcalendar@Easter@\the\count0\endcsname
{\the\pgfutil@tempcnta}%
\endgroup}
\pgfqkeys{/pgf/calendar/Easter}{
.default=0,
.code={%
\expandafter\ifx\csname pgfcalendar@Easter@\pgfcalendarifdateyear\endcsname\relax
\pgfcalendar@Easter{\pgfcalendarifdateyear}%
\fi
\expandafter\pgfutil@tempcnta
\csname pgfcalendar@Easter@\pgfcalendarifdateyear\endcsname
\advance\pgfutil@tempcnta#1\relax
\ifnum\pgfcalendarifdatejulian=\pgfutil@tempcnta
\pgfcalendarmatchestrue
\fi}}
\makeatother
\begin{document}
\begin{tikzpicture}
\calendar[dates=2012-04-01 to 2012-05-last, week list]
if (Easter=-3, % Maundy Thursday
Easter=-2, % Good Friday
Easter, % Easter Sunday
Easter=1, % Easter Monday
Easter=39, % Feast of the Ascension
Easter=49, % Pentecost
Easter=50) % Whit Monday
[red];
\end{tikzpicture}
\end{document}