3

I'm currently modifying the following calendar (TeXample) to match my needs and I wanted to rebuild the option where holidays are defined.

If you look at the code by Robert Krause you see, that he defines the holidays of the first six month in the first \begin{tikzfigure} and those of the last six month in the second tikzfigure-environment. To have a more maintainable calendar, I'd like to define the holidays in the preamble and let the calendar do the rest.

Furthermore I'd like to use this calendar for university, so I'd like to add exam dates which should be filled in red!20.

So I want to define all these holidays (fill with gray!30) and exam dates (fill with red!20) in the preamble and make the code dynamic. When compiling, tikz sould check if there are any exam dates defined and if so, it sould write the name in the corresponding field and fill that field red. If there are holidays defined it sould write their name in the field and fill it gray.

Here is a similar logic which I think I need, written in php:

<?php
$holidays = array(
        "2017-01-01" => "New Year",
        "2017-04-16" => "Easter Sunday",
        "2017-05-01" => "Labour Day",
        "2017-12-25" => "First Christmas Day"
    );

foreach( $holidays as $holiday => $name ){
    $date = strtotime($holiday);

    if($date <= strtotime("2017-06-30")) {
        // Place $name in the corrensponding field of the first six month and colour the field with gray!30
        echo "January to June: " . $name . "\r\n";
    }
    else if($date > strtotime("2017-06-30")) {
        // Place $name in the corrensponding field of the last six month and colour the field with gray!30
        echo "July to December: " . $name . "\r\n";
    }
}
?>

A similar behaviour for vacations where I could define the start and the end date and tikz would fill all the fields in bewteen gray would be awesome. At the moment, vacations also have to be defined in either of the tikzpicture-environments.

1
  • Why on Earth was this closed as being off-topic? Maybe one could argue that it needs further details as it relies on an external link and is not self-sustained, but off-topic seems a bit far fetched... Also it does have a nice answer. Why risk the question along with its anser being roombad by closing it? Jul 31 at 16:44

1 Answer 1

1

This is basically a copy from another answer of mine that deals with some kind of wall calendar but adjusted in some parts (mostly removing the schoolweek numbering).

The answer consists of these main parts:

  1. The month columns style sets up the dimensions (6 month per page with 5mm margin on both sides, 31 days per month plus space for the month label which is 1.2 times the height of a day), all the markings and also the placing of the actual nodes that make up the calendar.

  2. Two macros that should be filled like a \foreach list are used:

    1. \termine for fixed dates of the form

      <test> / <label> / <style>
      

      where <test> is just any PGFcalendar test and <style> is the style that should be applied for that day.

      In this example, I'm using different colors for holidays that aren't and those that are Christian.

    2. \bereiche for ranged of dates of the form

      <start>--<end> / <label> / <style>
      

      where <start>--<end> will be forwarded to between=<start> and <end> and <start> will be used to place the <label>.

  3. There are various markings style:

    • The “KW mark” marks the calendar week is set in the top right of the Monday
    • The mark up and the mark down where the former is used for ranges and the latter is used for the fixed dates.

    These styles are used in the bereiche and the termine key that parses the elements and sets up the markings as well as the styles.

  4. Then finally, a few styles are defined (that have been used in \termine and `\bereiche). These just set some colors.


The my calendar style brings that alltogether by using the month columns style and sets up a few colors for the labels as well as the weekend days (which are specified after bereiche and termine so that they override any coloring of the holidays, though we could also not apply their styles on weekends if we'd want).

I've chosen to put the year inside the month's label as a big 2022 just takes a lot of space that's better used for the calendar, in my opinion.

But it would certainly be possible to add the year on top of the calendar (even inside of \calendar) though we'd need to measure its height so that we fill the page efficiently.

The two pages are then just simply created by two TikZpictures:

\tikz\calendar[dates = 2023-01-01 to 2023-06-30, my calendar];
\tikz\calendar[dates = 2023-07-01 to 2023-12-31, my calendar];

Everything is in my calendar and there's no need for us to figure out which one is in the first or the second picture.

Since you have given no examples for your dates, I'm just using the public German holidays and the school breaks of Berlin.

It shouldn't be a big task to change a few styles and add your dates to get the output you want. (But feel free to ask anyway.)

Code

\documentclass[ngerman,multi=tikzpicture,varwidth=false]{standalone}
\usepackage{
  translator, % translator is used by the calendar library
  babel,      % provides the actual translations
  tikz,       % duh
  libertine}  % nice sf font
\usetikzlibrary{
  ext.calendar-plus} % nestable if, expandable shortcuts and week numbering
\tikzset{
  %%% the actual calendar style
  month columns/.style={% Mondays get yearweek number
    month width/.initial=(297mm-10mm)/6,   % 5mm borders on left and right side
    day height/.initial =(210mm-10mm)/32.2,% 5mm borders on the top and bottom
    day text={\%d=~~\%w.},
    textual/.style = {
      font=\strut,
      text depth=+0pt,
      outer sep=+0pt,
      anchor=south,
      text height=1em,
      text width=\pgfkeysvalueof{/tikz/month width}
                                        -2*(\pgfkeysvalueof{/pgf/inner xsep})},
    every day/.append style = {
      textual,
      align=left,
      minimum height=     \pgfkeysvalueof{/tikz/day height}},
    every month/.append style = {
      textual,
      align=center,
      minimum height=1.2*(\pgfkeysvalueof{/tikz/day height}),
      font=\Large\bfseries,
      label={[every year, anchor=base east]base east:\%y0},
      label={[every year, anchor=base west]base west:\%y0}},
    execute before day scope = {%
      \ifdate{day of month=1, equals=\pgfcalendarbeginiso}{\tikzmonthcode}{}%
      \ifdate{equals=\pgfcalendarbeginiso}{% in case cal doesn't start at 1st
        \pgftransformyshift{-(\%d--1)*(\pgfkeysvalueof{/tikz/day height})}}{}%
      \pgftransformyshift{-(\pgfkeysvalueof{/tikz/day height})}},
    execute after day scope = {%
      \ifdate{end of month=1}{% back up we go
        \pgftransformyshift{\%d-*(\pgfkeysvalueof{/tikz/day height})}%
        \pgftransformxshift{\pgfkeysvalueof{/tikz/month width}}}{}}}}
  
\newcommand*\termine{% repeating fixed day
  equals=01-01 / Neujahr             / Feiertag,
  equals=01-06 / Heilige Drei Könige / chrFeiertag,
  equals=03-08 / Int. Frauentag      / Feiertag,
  equals=05-01 / Tag der Arbeit      / Feiertag,
  equals=10-03 / Tag der dt. Einheit / Feiertag,
  equals=12-25 / 1. Weihnachtstag    / chrFeiertag,
  equals=12-26 / 2. Weihnachtstag    / chrFeiertag,
  Easter=-2    / Karfreitag          / chrFeiertag,
  Easter= 0    / Ostersonntag        / chrFeiertag,
  Easter= 1    / Ostermontag         / chrFeiertag,
  Easter=39    / Christi Himmelfahrt / chrFeiertag,
  Easter=49    / Pfingstsonntag      / chrFeiertag,
  Easter=50    / Pfingstmontag       / chrFeiertag}
\newcommand*\bereiche{% holidays
  2022-12-22--2023-01-02 / Weihnachtsferien      / Ferien,
  2023-01-30--2023-02-04 / Winterferien          / Ferien,
  2023-04-03--2023-04-14 / Osterferien           / Ferien,
  2023-05-19--2023-05-19 / Brückentag            / chrBruecke,
  2023-05-30--2023-05-30 / Pfingstferien         / Ferien,
  2023-07-13--2023-08-25 / Sommerferien          / Ferien,
  2023-10-02--2023-10-02 / Brückentag            / Bruecke,
  2023-10-23--2023-11-04 / Herbstferien          / Ferien,
  2023-12-23--2024-01-05 / Weihnachtsferien      / Ferien}
\tikzset{
  %%% marking styles
  mark up/.style         = {label = {[every mark up]   north west: #1}},
  mark down/.style       = {label = {[every mark down] south west: #1}},
  mark KW/.style         = {label = {[anchor=north east, every KW mark]
                                                  north east: KW~\%n-}},
  every KW mark/.style   = {every mark, text = gray!50!black},
  every mark/.style      = {font = \scriptsize, text = black,
                            text depth = +0pt, inner ysep = .3em},
  every mark up/.style   = {every mark, xshift = +3.3em, anchor=north west},
  every mark down/.style = {every mark, xshift = +3.3em, anchor=south west},
  %
  %%% Parsing
  bereiche/.style args={#1--#2/#3/#4}{
    if = {(between = #1 and #2) [
      if = {(workday)   [days = {style=#4}]},
      if = {(equals=#1) [days = {mark up = {#3}}]}
    ]},
  },
  termine/.style args = {#1/#2/#3}{
    if = {(#1) [days = {mark down = {#2},style=#3} ]}},
  %
  %%% visualization
  Feiertag/.style     = {fill = red!75,       },
  chrFeiertag/.style  = {fill = red!75!blue!50},
  Ferien/.style       = {fill = gray!25,      },
  Bruecke/.style      = {fill = red!67        },
  chrBruecke/.style   = {fill = red!75!blue!33}}
\tikzset{
  my calendar/.style = {
    month columns,
    every month/.append style={fill=red, text=white},
    every year/.append style={text=white},
    if = {(Monday) [days=mark KW]}, % Mondays get the week number
    bereiche/.list/.expand once=\bereiche,
    termine/.list/.expand once=\termine,
    if = {(Sunday)   [days={fill=red!50}]},
    if = {(Saturday) [days={fill=red!25}]}}}
\begin{document}
\sffamily\small
\tikz\calendar[dates = 2023-01-01 to 2023-06-30, my calendar];
\tikz\calendar[dates = 2023-07-01 to 2023-12-31, my calendar];
\end{document}

Output

enter image description here enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .