删除日历(tikz)中每一天的生日列表中的最后一个逗号

删除日历(tikz)中每一天的生日列表中的最后一个逗号

我正在采用这个日历(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}
 }

相关内容