Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm putting together a multi-month calendar in TikZ and am seeing some awkward and undesired alignment in the month labels despite using the month label above centered style. In particular, the month label appears to be centered only over the first six columns, rather than over all seven:

Observed vs Desired alignments of month label

I've reproduced my code below in a minimal context. Two questions: What's going on here, and how can I correct this alignment?

\documentclass[letterpaper]{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{calendar,shapes}

\makeatletter%
\tikzstyle{week list sunday}=[
        % Note that we cannot extend from week list,
        % the execute before day scope is cumulative
        execute before day scope={%
               \ifdate{day of month=1}{\ifdate{equals=\pgfcalendarbeginiso}{}{
               % On first of month, except when first date in calendar.
                   \pgfmathsetlength{\pgf@y}{\tikz@lib@cal@month@yshift}%
                   \pgftransformyshift{-\pgf@y}
               }}{}%
        },
        execute at begin day scope={%
            % Because for TikZ Monday is 0 and Sunday is 6,
            % we can't directly use \pgfcalendarcurrentweekday,
            % but instead we define \c@pgf@counta (basically) as:
            % (\pgfcalendarcurrentweekday + 1) % 7
            \pgfmathsetlength\pgf@x{\tikz@lib@cal@xshift}%
            \ifnum\pgfcalendarcurrentweekday=6
                \c@pgf@counta=0
            \else
                \c@pgf@counta=\pgfcalendarcurrentweekday
                \advance\c@pgf@counta by 1
            \fi
            \pgf@x=\c@pgf@counta\pgf@x
            % Shift to the right position for the day.
            \pgftransformxshift{\pgf@x}
        },
        execute after day scope={
            % Week is done, shift to the next line.
            \ifdate{Saturday}{
                % But not if it's already the last day of the month.
                \ifdate{end of month=1}{}{
                    \pgfmathsetlength{\pgf@y}{\tikz@lib@cal@yshift}%
                    \pgftransformyshift{-\pgf@y}
                }%
            }{}%
        },
        % This should be defined, glancing from the source code.
        tikz@lib@cal@width=7
    ]

\tikzoption{day headings}{\tikzstyle{day heading}=[#1]}
\tikzstyle{every calendar}=[week list sunday,
    month label above centered,
    month text=\textbf{\%mt~\%y-},
    day xshift = 0.5cm,
    day letter headings]
\tikzstyle{every day}=[anchor=base]
\tikzstyle{day heading}=[]
\tikzstyle{day letter headings}=[
    execute before day scope={ \ifdate{day of month=1}{%
      \pgfmathsetlength{\pgf@ya}{\tikz@lib@cal@yshift}%
      \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}%
      \pgftransformyshift{-\pgf@ya}
      \foreach \d/\l in {0/S,1/M,2/T,3/W,4/T,5/F,6/S} {
        \pgf@xa=\d\pgf@xa%
        \pgftransformxshift{\pgf@xa}%
        \pgftransformyshift{\pgf@ya}%
        \node[every day,day heading]{\l};%
      }
    }{}%
  }%
]

\makeatother%

% ==================================================

\begin{document}

\begin{tikzpicture}
\calendar (K) [dates=2013-01-01 to 2013-03-last]
    if (weekend) [black!40];
\draw[black](K-2013-01-21) circle (0.6em);
\draw[black](K-2013-02-13) circle (0.6em);
\draw[black](K-2013-03-10) circle (0.6em);
\draw[black](K-2013-03-31) circle (0.6em);
\end{tikzpicture}

\end{document}

Misaligned month label in TikZ calendar

share|improve this question

1 Answer 1

up vote 7 down vote accepted

You can increase the value for tikz@lib@cal@width for example, to 7.8:

\documentclass[letterpaper]{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{calendar,shapes}

\makeatletter%
\tikzstyle{week list sunday}=[
        % Note that we cannot extend from week list,
        % the execute before day scope is cumulative
        execute before day scope={%
               \ifdate{day of month=1}{\ifdate{equals=\pgfcalendarbeginiso}{}{
               % On first of month, except when first date in calendar.
                   \pgfmathsetlength{\pgf@y}{\tikz@lib@cal@month@yshift}%
                   \pgftransformyshift{-\pgf@y}
               }}{}%
        },
        execute at begin day scope={%
            % Because for TikZ Monday is 0 and Sunday is 6,
            % we can't directly use \pgfcalendarcurrentweekday,
            % but instead we define \c@pgf@counta (basically) as:
            % (\pgfcalendarcurrentweekday + 1) % 7
            \pgfmathsetlength\pgf@x{\tikz@lib@cal@xshift}%
            \ifnum\pgfcalendarcurrentweekday=6
                \c@pgf@counta=0
            \else
                \c@pgf@counta=\pgfcalendarcurrentweekday
                \advance\c@pgf@counta by 1
            \fi
            \pgf@x=\c@pgf@counta\pgf@x
            % Shift to the right position for the day.
            \pgftransformxshift{\pgf@x}
        },
        execute after day scope={
            % Week is done, shift to the next line.
            \ifdate{Saturday}{
                % But not if it's already the last day of the month.
                \ifdate{end of month=1}{}{
                    \pgfmathsetlength{\pgf@y}{\tikz@lib@cal@yshift}%
                    \pgftransformyshift{-\pgf@y}
                }%
            }{}%
        },
        % This should be defined, glancing from the source code.
        tikz@lib@cal@width=7.8
    ]

\tikzoption{day headings}{\tikzstyle{day heading}=[#1]}
\tikzstyle{every calendar}=[week list sunday,
    month label above centered,
    month text=\textbf{\%mt~\%y-},
    day xshift = 0.5cm,
    day letter headings]
\tikzstyle{every day}=[anchor=base]
\tikzstyle{day heading}=[]
\tikzstyle{day letter headings}=[
    execute before day scope={ \ifdate{day of month=1}{%
      \pgfmathsetlength{\pgf@ya}{\tikz@lib@cal@yshift}%
      \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}%
      \pgftransformyshift{-\pgf@ya}
      \foreach \d/\l in {0/S,1/M,2/T,3/W,4/T,5/F,6/S} {
        \pgf@xa=\d\pgf@xa%
        \pgftransformxshift{\pgf@xa}%
        \pgftransformyshift{\pgf@ya}%
        \node[every day,day heading]{\l};%
      }
    }{}%
  }%
]

\makeatother%

% ==================================================

\begin{document}

\begin{tikzpicture}
\calendar (K) [dates=2013-01-01 to 2013-03-last]
    if (weekend) [black!40];
\draw[black](K-2013-01-21) circle (0.6em);
\draw[black](K-2013-02-13) circle (0.6em);
\draw[black](K-2013-03-10) circle (0.6em);
\draw[black](K-2013-03-31) circle (0.6em);
\end{tikzpicture}

\end{document}

enter image description here

share|improve this answer
1  
Looks pretty good, but why 7.8, specifically? Is tikz@lib@cal@width effectively a multiple of day xshift? If so, why doesn't 7 work in this example? I'm trying to understand the root cause of the problem... –  Tim Parenti Nov 26 '12 at 2:53
    
After some experimentation, it seems the value which "correctly" centers the label in this example is 7.9, but I still don't have any additional insight into what that value actually represents and why 7 doesn't work as it should. –  Tim Parenti Nov 26 '12 at 3:41
    
@TimParenti I really don't know; I've never used the calendar library, so I am not familiar with how it works; I found the "dirty fix" by detecting which part of your code had to do with the horizontal alignment of the month label and that's how tikz@lib@cal@width appeared. The value 7.8 was found by trial/error. –  Gonzalo Medina Nov 26 '12 at 14:42
    
I suppose a "dirty fix" is better than no fix at all. Still leaves me with a bad taste, but hey... at least it works. I'm going to hold off on accepting this for another day or so in case anyone else can offer a more insightful solution. (But congrats on 100k!) –  Tim Parenti Nov 26 '12 at 22:13
    
@TimParenti sure, I would also like to know if someone offers a "proper" calculation ("manual" guessing are by no means my favorite either). Thanks for the congratulations. –  Gonzalo Medina Nov 26 '12 at 22:31

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.