我正在采用这个日历(https://texample.net/tikz/examples/birthday-calendar/) 满足我的需要,但我有一个无法自己解决的问题。
在每个单日网格中,如何删除生日列表(蓝色顶线)和特殊日子列表(绿色底线)中的最后一个逗号?
附加问题:第二行生日是否可以从日期数字开始?
这是我的代码:
% Birthday calendar
% Author: Hakon Malmedal
\documentclass[fontsize=15pt]{scrartcl}
\usepackage[german]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[paperheight=70cm,paperwidth=50cm,margin=0mm,heightrounded]{geometry}
%\usepackage[margin=1cm,a4paper,landscape]{geometry}
\pagestyle{empty}
\usepackage{graphicx}
\usepackage{tikz}
%%%<
\usepackage{verbatim}
%%%>
\begin{comment}
:Title: Birthday calendar
:Tags: Calendar library;Calendars
:Author: Hakon Malmedal
:Slug: birthday-calendar
\end{comment}
\usetikzlibrary{calendar,fit}
\usepackage{expl3,xparse}
%from https://tex.stackexchange.com/questions/140948/tikz-calendar-and-conditional-tests
\makeatletter
\def\pgfcalendar@matchesfalse{\global\let\ifpgfcalendar@matches\iffalse}
\def\pgfcalendar@matchestrue{\global\let\ifpgfcalendar@matches\iftrue}
\pgfcalendar@matchesfalse
\pgfqkeys{/pgf/calendar}{and/.code 2 args={%
\begingroup
\ifdate{#1}{\ifdate{#2}{\pgfcalendar@matchestrue}{}}{}%
\endgroup
\ifpgfcalendar@matches\pgfcalendarmatchestrue\pgfcalendar@matchesfalse\fi}}
\makeatother
%% Adapted from pgf source
\def\pgfcalendarmonthname#1{%
\translate{\ifcase#1\or Januar\or Februar\or März\or April\or
Mai\or Juni\or Juli\or August\or September\or Oktober\or
November\or Dezember\fi}%
}
%% Adapted from http://tex.stackexchange.com/a/10199/4771
\makeatletter%
\tikzoption{day headings}{\tikzstyle{day heading}=[#1]}
\tikzstyle{day heading}=[]
\tikzstyle{day letter headings}=[
execute before day scope={ \ifdate{equals=01-01}{%
\pgfmathsetlength{\pgf@ya}{\tikz@lib@cal@yshift}%
\pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}%
\pgftransformyshift{-\pgf@ya}
\foreach \d/\l in {0/Montag,1/Dienstag,2/Mittwoch,3/Donnerstag,%
4/Freitag,5/Samstag,6/Sonntag} {
\pgf@xa=\d\pgf@xa%
\pgftransformxshift{\pgf@xa-\cellwidth/2}%
\pgftransformyshift{2\pgf@ya-2pt}%
\node[below=0.5ex,day heading, inner sep=2.5mm,font=\Large]{\l};%
}
}{}%
}%
]
\makeatother%
%% End
\ExplSyntaxOn
%% Adapted from http://tex.stackexchange.com/a/56214/4771
%%
% first of all we define the user level commands
\NewDocumentCommand{\addtext}{ m }{ \bdaycal_input_add_text:n { #1 } }
\NewDocumentCommand{\addbirthday}{ mm }{ \bdaycal_input_add_birthday:nn { #1 } { #2 } }
\NewDocumentCommand{\addbirthdaydead}{ mm }{ \bdaycal_input_add_birthday_dead:nn { #1 } { #2 } }
\NewDocumentCommand{\adddateofdeath}{ mm }{ \bdaycal_input_add_date_of_death:nn { #1 } { #2 } }
\NewDocumentCommand{\addweek}{ m }{ \bdaycal_input_add_week:n { #1 } }
\NewDocumentCommand{\showtext}{ }{ \bdaycal_output_direct_text: }
\NewDocumentCommand{\showbirthdays}{ }{ \bdaycal_output_direct_birthday: }
% allocate variable:
% a sequence for global storage of the inputs;
\seq_new:N \g_bdaycal_input_seq_text
\seq_new:N \g_bdaycal_input_seq_birthday
% store globally an input in the sequence
\cs_new:Npn \bdaycal_input_add_text:n #1
{
\seq_gput_right:Nn \g_bdaycal_input_seq_text { #1 }
}
\cs_new:Npn \bdaycal_input_add_birthday:nn #1 #2
{
\seq_gput_right:Nn \g_bdaycal_input_seq_birthday { #1 ~ \int_to_arabic:n
{ \pgfcalendarifdateyear - #2 }}
}
\cs_new:Npn \bdaycal_input_add_birthday_dead:nn #1 #2
{
\seq_gput_right:Nn \g_bdaycal_input_seq_birthday {( #1 ~ \int_to_arabic:n
{ \pgfcalendarifdateyear - #2 })}
}
\cs_new:Npn \bdaycal_input_add_date_of_death:nn #1 #2
{
\seq_gput_right:Nn \g_bdaycal_input_seq_birthday {\dag \ #1 ~ #2}
}
% how to output in direct order; we simply do a mapping function calling
% \bdaycal_print:n after incrementing the counter
\cs_new_protected:Npn \bdaycal_output_direct_text:
{
\seq_map_inline:Nn \g_bdaycal_input_seq_text
{
\int_gincr:N \g_tmpa_int
% \int_compare:nNnT {\g_tmpa_int}={1}{}%vor dem ersten Eintrag
##1
\int_compare:nNnF {\g_tmpa_int}={\seq_count:N \g_bdaycal_input_seq_text}{,~}%am Ende jedes Eintrags, außer nach dem letzten
}
\seq_gclear:N \g_bdaycal_input_seq_text
}
\cs_new_protected:Npn \bdaycal_output_direct_birthday:
{
\seq_map_inline:Nn \g_bdaycal_input_seq_birthday
{
\int_gincr:N \g_tmpa_int
% \int_compare:nNnT {\g_tmpa_int}={1}{}%vor dem ersten Eintrag
##1
\int_compare:nNnF {\g_tmpa_int}={\seq_count:N \g_bdaycal_input_seq_birthday}{,~}%am Ende jedes Eintrags, außer nach dem letzten
}
\seq_gclear:N \g_bdaycal_input_seq_birthday
}
%% End
%% 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 }
}
}
\int_new:N \l_advent_Y_int
\int_new:N \l_advent_xmas_julian_day_int
\int_new:N \l_advent_xmas_week_day_int
\int_new:N \l_advent_julian_day_int
\cs_new:Nn \advent_sunday:n {
\int_set:Nn \l_advent_Y_int { #1 }
\pgfcalendardatetojulian { \l_advent_Y_int - 12 - 25 } {
\l_advent_xmas_julian_day_int }
\pgfcalendarjuliantoweekday { \l_advent_xmas_julian_day_int } {
\l_advent_xmas_week_day_int }
\int_set:Nn \l_advent_julian_day_int {
\l_advent_xmas_julian_day_int - \l_advent_xmas_week_day_int - 22 }
}
\ExplSyntaxOff
\pgfkeys{/tikz/observance/.code =
{
\addtext{#1}
}
}
\pgfkeys{/tikz/anniversary/.code 2 args=\addbirthday{#1}{#2}}
\pgfkeys{/tikz/anniversary_dead/.code 2 args=\addbirthdaydead{#1}{#2}}
\pgfkeys{/tikz/date_of_death/.code 2 args=\adddateofdeath{#1}{#2}}
\pgfkeys{/tikz/day code =
{
\node (lower right) at (-1pt,1pt){};
\node (upper left) at (-\cellwidth +1pt,\cellheight -1pt){};
\node (day of month) at (-\cellwidth + 3pt,0.3\cellheight) [above right,font=\bfseries\Large] {\tikzdaytext};
\node (birthdays) at (-\cellwidth +2pt,\cellheight -2pt)
[below right,align=left,text width=\cellwidth-3pt,
font=\tiny\bfseries,blue] {\showbirthdays};
\node (name of day) at (-\cellwidth +2pt,8pt)
[below right,align=left,text width=\cellwidth-\pgflinewidth,
font=\tiny,green] {\showtext};
\node[draw,
fit=(lower right) (upper left),
inner sep=0mm] {};
}
}
\pgfkeys{/tikz/inner sep = 0pt}
\pgfkeys{/tikz/day xshift=\cellwidth}
\pgfkeys{/tikz/day yshift=\cellheight}
\pgfkeys{/tikz/month yshift=0mm}
\newlength{\cellheight}
\setlength{\cellheight}{13mm}
\newlength{\cellwidth}
\setlength{\cellwidth}{68mm}
\begin{document}
\centering
\begin{tikzpicture}[thick]
\calendar[dates=2021-01-01 to 2021-12-last,
week list,
day headings={font=\footnotesize},
day letter headings
]
if (%Sunday,
% 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
equals=01-01,%Neujahr
equals=03-08,%Internationaler Frauentag (nur Berlin)
equals=05-01,%Tag der Arbeit
equals=10-03,%Tag der deutschen Einheit
equals=12-25,%1. und 2. Weihnachtsfeiertag
equals=12-26) [red]
if (Easter=-48) [observance=Rosenmontag]
if (Easter=-46) [observance=Aschermittwoch]
if (Easter=-7) [observance=Palmsonntag]
if (Easter=-3) [observance=Gründonnerstag]
if (Easter=-2) [observance=Karfreitag]
if (Easter) [observance=Ostersonntag]
if (Easter=1) [observance=Ostermontag]
if (Easter=39) [observance=Christi Himmelfahrt]
if (Easter=39) [observance=Vatertag]
if (Easter=49) [observance=Pfingstsonntag]
if (Easter=50) [observance=Pfingstmontag]
if (Easter=59) [observance=Fronleichnam]
if (equals=01-01) [observance=Neujahr]
if (equals=01-06) [observance=Heilige drei Könige]
if (equals=02-14) [observance=Valentinstag]
if (equals=03-08) [observance=Internationaler Frauentag]
if (equals=05-01) [observance=Tag der Arbeit]
if (equals=05-08) [observance=Tag der Befreiung / Ende WWII 1945]
if (equals=08-15) [observance=Mariä Himmelfahrt]
if (equals=10-03) [observance=Tag der deutschen Einheit 1990]
if (equals=10-31) [observance=Reformationstag]
if (equals=10-31) [observance=Halloween]
if (equals=11-01) [observance=Allerheiligen]
if (equals=11-09) [observance=Fall der Mauer 1989]
if (equals=11-09) [observance=Novemberprogrome 1938]
if (equals=12-24) [observance=Heilig Abend]
if (equals=12-25) [observance=1. Weihnachtstag]
if (equals=12-26) [observance=2. Weihnachtstag]
if (equals=12-31) [observance=Silvester]
if (and={between=11-16 and 11-22}{Wednesday}) [observance=Buß- und Bettag]
if (and={between=11-13 and 11-19}{Sunday}) [observance=Volkstrauertag]
if (and={between=11-20 and 11-26}{Sunday}) [observance=Totensonntag]
if (and={between=11-27 and 12-03}{Sunday}) [observance=1. Advent]
if (and={between=12-04 and 12-10}{Sunday}) [observance=2. Advent]
if (and={between=12-11 and 12-17}{Sunday}) [observance=3. Advent]
if (and={between=12-18 and 12-24}{Sunday}) [observance=4. Advent]
if (and={between=03-25 and 03-31}{Sunday}) [observance=Beginn Sommerzeit]%letzter Sonntag im März
if (and={between=10-25 and 10-31}{Sunday}) [observance=Ende Sommerzeit]%letzter Sonntag im Oktober
if (and={between=05-08 and 05-14}{Sunday}) [observance=Muttertag]%2. Sonntag im Mai
if (equals=12-06) [observance=Nikolaus]
if (equals=07-17) [anniversary={John Smith}{2018}]
if (equals=12-07) [anniversary={John Smith}{1982}]
if (equals=01-04) [anniversary={John Smith}{1983}]
if (equals=01-18) [anniversary={John Smith}{1985}]
if (equals=10-23) [anniversary={John Smith}{1986}]
if (equals=08-29) [anniversary={John Smith}{1954}]
if (equals=10-14) [anniversary={John Smith}{1954}]
if (equals=03-01) [anniversary_dead={John Smith}{1923}]
if (equals=05-24) [date_of_death={John Smith}{2011}]
if (equals=12-01) [anniversary={John Smith}{1927}]
if (equals=08-29) [anniversary={John Smith}{2013}]
if (equals=08-29) [anniversary={John Smith}{1981}]
;
\end{tikzpicture}
\end{document}
答案1
下面的代码解决了这个问题:
\int_new:N \g_counter_int
\cs_new_protected:Npn \bdaycal_output_direct_text:
{
\seq_map_inline:Nn \g_bdaycal_input_seq_text
{
\int_add:Nn \g_counter_int { 1 }
##1
\int_compare:nNnF {\g_counter_int}={\seq_count:N \g_bdaycal_input_seq_text}{,~}
}
\seq_gclear:N \g_bdaycal_input_seq_text
\int_set:Nn \g_counter_int {0}
}
\cs_new_protected:Npn \bdaycal_output_direct_birthday:
{
\seq_map_inline:Nn \g_bdaycal_input_seq_birthday
{
\int_add:Nn \g_counter_int { 1 }
##1
\int_compare:nNnF {\g_counter_int}={\seq_count:N \g_bdaycal_input_seq_birthday}{,~}
}
\seq_gclear:N \g_bdaycal_input_seq_birthday
\int_set:Nn \g_counter_int {0}
}