如何定义某个时间段的日历事件

如何定义某个时间段的日历事件

这个问题是我之前关于如何测试日期是否在日历上

这里我想问一下如何进一步修改我的代码以减少逐个输入所有事件的工作。正如您在下面的最小示例中看到的那样(与上一个问题除了实践课程的日期外,我目前必须单独添加每个日期。我该如何修改日历代码来将事件打印到日历中以了解以下命令结构:

\newcommand{\practicalCourses}{
    {Course Name}/{beginDate}/{endDate},%
    {Other Course Name}/{other beginDate}/{other endDate}%
}

代码应该循环遍历每个课程的beginDate和之间的所有日期(endDate课程名其他课程名称在这个例子中),然后测试该日期是否在日历上(在calbegindate和之间calenddate参见上一个问题),如果是,则打印相应日期的课程名称。


平均能量损失

% %%%%%%%%
% Preamble
% %%%%%%%%

\documentclass[10pt, a4paper, landscape]{article}
\usepackage[margin = .5cm, nofoot]{geometry}

% Tikz
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{calendar}

% Logic and Tools
\usepackage{xparse}

% Fonts
\RequirePackage{lmodern}
\renewcommand*\familydefault{\sfdefault}

% Color
\definecolor{definedcolor}{HTML}{00CC00}

% Calculation
\ExplSyntaxOn
    \DeclareExpandableDocumentCommand{\eval}{m}{\int_eval:n {#1}}
\ExplSyntaxOff

% Custom appearance
\newcommand{\practicalCourse}[2]{%
    \node [text=black, anchor = north west, text width = 3.3cm ] at ($(cal-#1.north west)+(3.5em, -0.2em)$) {\scriptsize{#2}};
}

% Variables
\newcommand{\currentyear}{\the\year}
\newcommand{\nextyear}{\eval{\currentyear + 1}}

\newcommand{\calbegindate}{\currentyear-10-01}
\newcommand{\calenddate}{\nextyear-03-31}

\newcommand{\practicalCourses}{%
    {Foo}/\currentyear-10-09,%
    {Foo}/\currentyear-10-10,%
    {Foo}/\currentyear-10-11,%
    {Foo}/\currentyear-10-12,%
    {Foo}/\currentyear-10-13,%
    {Foo}/\currentyear-10-16,%
    {Foo}/\currentyear-10-17,%
    {Foo}/\currentyear-10-18,%
    {Foo}/\currentyear-10-19,%
    {Foo}/\currentyear-10-20,%
    {Foo}/\currentyear-10-23,%
    {Foo}/\currentyear-10-24,%
    {Foo}/\currentyear-10-25,%
    {Foo}/\currentyear-10-26,%
    {Foo}/\currentyear-10-27,%
    {Bar}/\currentyear-11-06,%
    {Bar}/\currentyear-11-07,%
    {Bar}/\currentyear-11-08,%
    {Bar}/\currentyear-11-09,%
    {Bar}/\currentyear-11-10,%
    {Bar}/\currentyear-11-13,%
    {Bar}/\currentyear-11-14,%
    {Bar}/\currentyear-11-15,%
    {Bar}/\currentyear-11-16,%
    {Bar}/\currentyear-11-17%
}

% What I want to do:
% \newcommand{\practicalCourse}{%
%     {Foo}/{\currentyear-10-09}/{\currentyear-11-10},%
%     {Bar}/{\currentyear-11-06}/{\currentyear-11-17}
% }

% Define searchable object (\ifdate{PracticalCourse})
\ExplSyntaxOn
    \clist_new:N \g_practical_course_clist%
    \int_new:N \l_practical_course_int%
    \foreach \i/\j in \practicalCourses {%
        \pgfcalendardatetojulian{\j}{\l_practical_course_int}%
        \clist_gput_right:Nx \g_practical_course_clist {%
            \int_to_arabic:n { \l_practical_course_int }%
        }%
    }%
    \cs_new_protected_nopar:Nn \practical_course_test:n {%
        \int_set:Nn \l_tmpa_int {#1}%
            \clist_if_in:NVT \g_practical_course_clist \l_tmpa_int {%
            \pgfcalendarmatchestrue%
        }%
    }%
    \cs_generate_variant:Nn \practical_course_test:n {x}%
    \NewDocumentCommand \testpraktikum { m } {%
        \practical_course_test:x { #1 }%
    }%
\ExplSyntaxOff

\tikzset{
    /pgf/calendar/PracticalCourse/.code={%
        \testpraktikum{\pgfcalendarifdatejulian}%
    },
}


% %%%%%%%%%%%%%%
% Begin Document
% %%%%%%%%%%%%%%

\begin{document}
    \centering
    \begin{tikzpicture}[every day/.style={anchor = north}]
        \calendar[
            dates = \calbegindate to \calenddate,
            name = cal,
            day yshift = 3em,
            day code = {
                \node[name = \pgfcalendarsuggestedname, every day, minimum height = .53cm, text width = 4.4cm, draw = gray] {\tikzdaytext};
                \draw (-1.8cm, -.1ex) node [anchor = west, font=\footnotesize] {\pgfcalendarweekdayshortname{\pgfcalendarcurrentweekday}};
            },
            execute before day scope={
                \ifdate{day of month = 1} {
                    \pgftransformxshift{4.8cm}
                    \draw (0,0) node [minimum height = .53cm, text width = 4.4cm, fill = definedcolor, text = white, draw = definedcolor, text centered] {\textbf{\pgfcalendarmonthname{\pgfcalendarcurrentmonth}\strut}};
                }{}
                \ifdate{workday} {
                    \tikzset{every day/.style = {fill = white}}
                    \ifdate{PracticalCourse}{%
                        \tikzset{every day/.style = {fill = olive!30}}%
                    }{}
                }{}
                \ifdate{Saturday} {
                    \tikzset{every day/.style = {fill = definedcolor!10}}%
                }{}
                \ifdate{Sunday} {
                    \tikzset{every day/.style = {fill = definedcolor!20}}%
                }{}
            },
            execute at begin day scope = {
                \pgftransformyshift{-.53*\pgfcalendarcurrentday cm}
            }
        ];
        \foreach \subject/\eventdate in \practicalCourses {
            \practicalCourse{\eventdate}{\subject}
        }
    \end{tikzpicture}
\end{document}

答案1

我改变了一些东西。

它的核心是一个键,我们可以控制条件(两个日期之间)和注释(Foo 或 Bar)。

这可以通过密钥完成

/tikz/if=(<cond>) <true> else <false>

其中<true><else>可以是[<style>]或,{<code>}并且else <false>部分是可选的。

为了排版注释,我使用了label远离xshift = 3.5em日期节点左侧但在基线(base west锚点)垂直对齐的注释。

由于日期重叠,我们不能仅仅使用,label=[<opts>]<dir>:#1因为这样我们会得到多个相互重叠的标签。

我已经进行了调整,day code以便当日记录尝试possible label使用来自的值collected labels(当它仍然可以访问时 - 这样做label=\pgfkeysvalueof{/tikz/collected label}是行不通的,因为节点选项在它们自己的组/范围内。

但是我们也不希望每个每天的节点都尝试设置标签,这就是为什么我们仅在我们的条件适用时才使用activate label设置键。possible label

关于条件,我使用了我图书馆的and钥匙ext.calendar-plistikz-ext包裹

代码

\documentclass[tikz]{standalone}

\usetikzlibrary{ext.calendar-plus}% loads calendar library

% Fonts
\RequirePackage{lmodern}
\renewcommand*\familydefault{\sfdefault}

% Color
\definecolor{definedcolor}{HTML}{00CC00}

% Calculation
\ExplSyntaxOn
    \DeclareExpandableDocumentCommand{\eval}{m}{\int_eval:n {#1}}
\ExplSyntaxOff

% Variables
\newcommand{\currentyear}{\the\year}
\newcommand{\nextyear}{\eval{\currentyear + 1}}
\newcommand{\calbegindate}{\currentyear-10-01}
\newcommand{\calenddate}{\nextyear-03-31}

\newcommand*{\practicalCourses}{
     {Foo}/{\currentyear-10-09}/{\currentyear-11-10},
     {Bar}/{\currentyear-11-06}/{\currentyear-11-17}}

\begin{document}
\begin{tikzpicture}[
  every day/.style={anchor = north},
  collect label/.style={
    collected labels/.initial={#1},
    collect label/.style={
      collected labels/.append={, ##1}}},
  %
  %%% is basically a \def\keymacro#1/#2/#3\STOP{<…>}
  %%% with the /tikz/if key we can control both conditions
  %%% and the true/false options/code
  %%%
  PracticalCourse/.style args={#1/#2/#3}{
    if={(and={workday, between=#2 and #3})[
      days={fill=olive!30, activate label, collect label={#1}}
    ]}
  },
  %
  %%% activate label sets the possible label style
  %%% that uses the argument of possible label
  %%% hence ##1 and not #1 ( = would be value to activate label)
  activate label/.style={
    possible label/.style={
      label={[text=black, text width = 3.1cm, xshift=3.5em, anchor=base west,
        font=\scriptsize]base west:##1}},
    activate label/.style=% deactivate me
  }]
\calendar[
  dates = \calbegindate to \calenddate,
  name = cal,
  day yshift = 3em,
  day code = {
    \node[name = \pgfcalendarsuggestedname, every day, minimum height = .53cm, text width = 4.4cm, draw = gray,
      %
      %%% try the possible label with the content of /tikz/collected labels
      %%% needs to be expanded because the value os lost after the node
      %%%
      possible label/.try/.expand twice/.expand once=
        \pgfkeysvalueof{/tikz/collected labels}
    ] {\tikzdaytext};
    \draw (-1.8cm, -.1ex) node [anchor = west, font=\footnotesize] {\%w.};
  },
  execute before day scope={
      \ifdate{day of month = 1} {%
          \pgftransformxshift{4.8cm}%
          \node [minimum height = .53cm, text width = 4.4cm,
            fill = definedcolor, text = white, draw = definedcolor,
            text centered] {\textbf{\%mt\strut}};
      }{}%
      \ifdate{workday} {%
          \tikzset{every day/.style = {fill = white}}%
      }{}%
      \ifdate{Saturday} {%
          \tikzset{every day/.style = {fill = definedcolor!10}}%
      }{}%
      \ifdate{Sunday} {%
          \tikzset{every day/.style = {fill = definedcolor!20}}%
      }{}%
  },
  execute at begin day scope = {%
      \pgftransformyshift{-.53*\pgfcalendarcurrentday cm}%
  },
  %%% actual test four courses
  PracticalCourse/.list/.expand once=\practicalCourses
];
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

相关内容