语境
我有很多(约 20+ 个)日期(或范围)出于兴趣 已派遣超过 5 年calendar
。
浪费了太多空间!
我的问题
日期很少的日历有点帮助(给“无用”的日期上色),但是我怎样才能在下面过滤日历,只有当其中使用日期时我才能获得月份?
在上面的例子中,日历从 2018 年 5 月到 2022 年 8 月。它对应 52 行,52 个月。然而,这 52 行中有 44 行是“空的”,因为我输入的日期都没有显示在那里。因此,我想按月显示相同的内容,但我只能得到 8 行月份。
May18
Jun18
Jul18
Jul19
Jul20
Jul21
Jul22
Aug22
平均能量损失
\documentclass[12pt,tikz]{standalone}
%\usepackage[french]{babel}
%\usepackage[french]{translator}
\usetikzlibrary{calendar}
\makeatletter
\pgfkeys{/pgf/calendar/start of year/.code={%
\ifnum\pgfcalendarifdateday=1\relax%
\ifnum\pgfcalendarifdatemonth=1\relax\pgfcalendarmatchestrue\fi%
\fi%
}}%
% Define our own style
\tikzset{week list sunday/.style={execute at begin day scope={%
% Because for TikZ Monday is 0 and Sunday is 6,
% we can't directly use \pgfcalendercurrentweekday,
% but instead we define \c@pgf@counta (basically) as:
% (\pgfcalendercurrentweekday + 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}
}},
tikz@lib@cal@width=7}
% New style for drawing the year, it is always drawn
% for January
\tikzset{year label left/.style={
execute before day scope={
\ifdate{start of year}{
\drawyear
}{}
},
% Right align
every year/.append style={
anchor=east,
xshift=-6em
}},
N_date/.style={circle,very thick,draw=red}
}
% This actually draws the year.
\newcommand{\drawyear}{
\pgfmathsetlength{\pgf@x}{\tikz@lib@cal@xshift}%
\pgftransformxshift{-\pgf@x}
% \tikzyearcode is defined by default
\tikzyearcode
\pgfmathsetlength{\pgf@x}{\tikz@lib@cal@xshift}%
\pgftransformxshift{\pgf@x}
}
\makeatother
% I define my dates of interest
\def\SCal{2018-05-01}
\def\ECal{2022-08-last}
\def\SNego{2018-05-11}
\def\ENego{2018-06-11}
\def\Deal{2018-06-12}
\def\PreStrike{2018-06-12}
\def\Issue{2018-06-27}
\def\SComm{2018-06-28}
\def\EComm{2018-07-28}
\def\Strike{2018-07-29}
\def\ConstatOne{2019-07-29}
\def\ConstatTwo{2020-07-29}
\def\ConstatThree{2021-07-29}
\def\ConstatFour{2022-07-29}
\def\ConstatFive{2022-07-29}
\def\FinalValue{2022-07-29}
\def\Maturity{2022-08-10}
\begin{document}
\begin{tikzpicture}
\calendar (CalPS)[
dates=\SCal to \ECal,
year label left,
every year/.append style={font=\Large\sffamily\bfseries,
orange!50!black},
month list,
month label left,
month yshift=1.25em,
days={
gray!20,
text width=width("00"),
align=center,
% inner xsep=
% .5*\csname tikz@lib@cal@xshift\endcsname-.5*\csname tikz@text@width\endcsname,
% inner ysep=.5*\csname tikz@lib@cal@month@yshift\endcsname-.5*height("0")
}
]
%---------- Phase 1 ------------------------------
if (between=\SNego and \ENego) [days={fill=green!50}]
%---------- Phase 2 ------------------------------
if (equals=\Deal) [days={fill=green!80,rectangle}, red]
%---------- Phase 3------------------------------
if (equals=\PreStrike) [days={fill=red!80,rectangle}]
%---------- Phase 4 ------------------------------
if (equals=\Issue) [days={fill=blue!80,rectangle}]
%---------- Phase 5------------------------------
if (between=\SComm and \EComm) [days={fill=green!90}]
%---------- Phase 6------------------------------
if (equals=\Strike) [days={fill=red!80,rectangle}]
%---------- Phase 7 ------------------------------
if ( equals=\ConstatOne,
equals=\ConstatTwo,
equals=\ConstatThree,
equals=\ConstatFour,
equals=\ConstatFive,
) [days={fill=orange!80,rectangle}]
%---------- Phase 8 ------------------------------
if (equals=\FinalValue) [days={fill=red!80,rectangle}]
%---------- Phase 9 ------------------------------
if (equals=\Maturity) [days={fill=blue!80,rectangle}]
;
\end{tikzpicture}
\end{document}
注意:是不是只有我一个人注意到calendar
TexSE 上的大多数例子都很旧了Tikzstyle
?
答案1
我没有看到图书馆有任何界面可以跳过日期,尤其是不if
适用的月份。您需要更改\ifdate
以收集所有日期,以便在月份/年份开始时查找这些日期。
我的解决方案是检查当前月份/年份是否在要跳过的日期列表中,然后直接跳到该月份/年份的最后一天,而不对跳过的月份/年份的第一天执行任何操作。
我将其重写month list
为month list with skipped months
,它接受两个参数:
- 整整一年要跳过,
- 需要跳过的月份
我没有使用年份,也没有测试过,所以祝你好运。月份以列表格式给出,因此无需手动提供后续月份:
month list with skipped months={}{
2018:8 to 12,
2019:1 to 6,
2019:8 to 12,
2020:1 to 6,
2020:8 to 12,
2021:2 to 6, % kept January in to test a proper start of the year
2021:8 to 12,
2022:1 to 6
},
我们需要在是方向,因为我们必须抵消在月初进行的降档,而我们在检查跳过时并没有这样做。
我不喜欢它,但它是我能想到的最干净的办法。
代码
every month/.append code=\ifdate{skipped month}{\pgfkeysalso{shape=coordinate}}{},
用于隐藏跳过的月份名称。
代码
\documentclass[12pt,tikz,convert]{standalone}
\usetikzlibrary{calendar}
\pgfset{
calendar/start of year/.code={% check for start of year
\ifnum\pgfcalendarifdateday=1\relax%
\ifnum\pgfcalendarifdatemonth=1\relax\pgfcalendarmatchestrue\fi%
\fi}}
\tikzset{% setting up the collections, used by month list with skipped months
skipper/setup year skips/.style={
/utils/exec=\def\listSkipYear{,},
skipper/years/.list={#1}},
skipper/years/.code=%
\edef\listSkipYear{\listSkipYear#1,},
skipper/setup month skips/.style={
/utils/exec=\def\listSkipMonth{,},
skipper/months/.list={#1}},
skipper/months/.style args={#1:#2to#3}{
skipper/@/.code=%
\edef\listSkipMonth{\listSkipMonth#1-\ifnum##1<10 0\fi##1,},
skipper/@/.list={#2,...,#3}},
}
\makeatletter
\pgfset{% \ifdate lookups for year or year-months
calendar/skipped year/.code=%
\edef\pgf@cal@temp{{,\pgfcalendarifdateyear,}{\listSkipYear}}%
\expandafter\pgfutil@in@\pgf@cal@temp
\let\ifpgfcalendarmatches\ifpgfutil@in@,
calendar/skipped month/.code=%
\edef\pgf@cal@temp
{{,\pgfcalendarifdateyear-\pgfcalendarifdatemonth,}{\listSkipMonth}}%
\expandafter\pgfutil@in@\pgf@cal@temp
\let\ifpgfcalendarmatches\ifpgfutil@in@
}
\newif\ifSkipDay
\tikzset{
month list with skipped months/.style 2 args={%
skipper/setup year skips={#1},
skipper/setup month skips={#2},
every month/.append code=%
\ifdate{skipped month}{\pgfkeysalso{shape=coordinate}}{},
execute before day scope={%
\SkipDayfalse
\ifdate{day of month=1}{% do the test only on the first of the month
\ifdate{skipped year}{% skip straight to the nye
\pgfcalendardatetojulian
{\pgfcalendarcurrentyear-12-31}\pgfcalendarcurrentjulian
\SkipDaytrue
}{%
\ifdate{equals=\pgfcalendarbeginiso}{% start of the calendar is never skipped
\drawyear % every first (even the very first) we shift down, counteract %
\pgfmathsetlength{\pgf@y}{\tikz@lib@cal@month@yshift}% %
\pgftransformyshift{+\pgf@y}% %
\begingroup % from original month list style %%%%%%%%%%%%%%%
\c@pgf@counta=\pgfcalendarcurrentjulian% %
\advance\c@pgf@counta by-\pgfcalendarcurrentday% %
\advance\c@pgf@counta by1\relax% %
\pgfcalendarjuliantoweekday{\c@pgf@counta}{\c@pgf@countb}%
\xdef\pgf@temp{\the\c@pgf@countb}% %
\endgroup %
\let\tikz@lib@cal@month@list@start=\pgf@temp% %
}{%
\ifdate{start of year}{%
\pgfmathsetlength{\pgf@y}{\tikz@lib@cal@month@yshift}%
\pgftransformyshift{+-\pgf@y}%
\drawyear % every first (even the very first) we shift down, counteract %
\pgfmathsetlength{\pgf@y}{\tikz@lib@cal@month@yshift}% %
\pgftransformyshift{+\pgf@y}% %
}{}%
}%
\ifdate{skipped month}{%
\pgfcalendardatetojulian
{\pgfcalendarcurrentyear-\pgfcalendarcurrentmonth-last}%
\pgfcalendarcurrentjulian
\SkipDaytrue
}{}%
}%
}{}%
%
\ifSkipDay\else
\ifdate{day of month=1}{% from original month list style %%%%%%%%%
\pgfmathsetlength{\pgf@y}{\tikz@lib@cal@month@yshift}% %
\pgftransformyshift{+-\pgf@y}% %
\edef\tikz@lib@cal@month@list@start{\pgfcalendarcurrentweekday}%
}{}%
\fi
},%
execute at begin day scope={% from original month list style %
\pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}% %
\pgf@xb=\pgfcalendarcurrentday\pgf@xa% %
\advance\pgf@xb by\tikz@lib@cal@month@list@start\pgf@xa% %
\advance\pgf@xb by-\pgf@xa\relax% %
\pgftransformxshift{\pgf@xb}% %
}, %
tikz@lib@cal@width=37 %
},
}
% This actually draws the year.
\newcommand{\drawyear}{
\pgfmathsetlength{\pgf@x}{\tikz@lib@cal@xshift}%
\pgftransformxshift{-\pgf@x}
% \tikzyearcode is defined by default
\tikzyearcode
\pgfmathsetlength{\pgf@x}{\tikz@lib@cal@xshift}%
\pgftransformxshift{\pgf@x}
}
\makeatother
% I define my dates of interest
\def\SCal{2018-05-01}
\def\ECal{2022-08-last}
\def\SNego{2018-05-11}
\def\ENego{2018-06-11}
\def\Deal{2018-06-12}
\def\PreStrike{2018-06-12}
\def\Issue{2018-06-27}
\def\SComm{2018-06-28}
\def\EComm{2018-07-28}
\def\Strike{2018-07-29}
\def\ConstatOne{2019-07-29}
\def\ConstatTwo{2020-07-29}
\def\ConstatThree{2021-07-29}
\def\ConstatFour{2022-07-29}
\def\ConstatFive{2022-07-29}
\def\FinalValue{2022-07-29}
\def\Maturity{2022-08-10}
\begin{document}
\begin{tikzpicture}
\calendar (CalPS)[
dates=\SCal to \ECal,
every year/.append style={
font=\sffamily\bfseries, orange!50!black, anchor=base east, xshift=-6em},
month list with skipped months={}{
2018:8 to 12,
2019:1 to 6,
2019:8 to 12,
2020:1 to 6,
2020:8 to 12,
2021:2 to 6,
2021:8 to 12,
2022:1 to 6
},
month label left,
month yshift=1.25em,
days={gray!20, text width=width("00"), align=center}
]
%---------- Phase 1 ------------------------------
if (between=\SNego and \ENego) [days={fill=green!50}]
%---------- Phase 2 ------------------------------
if (equals=\Deal) [days={fill=green!80,rectangle}, red]
%---------- Phase 3------------------------------
if (equals=\PreStrike) [days={fill=red!80,rectangle}]
%---------- Phase 4 ------------------------------
if (equals=\Issue) [days={fill=blue!80,rectangle}]
%---------- Phase 5------------------------------
if (between=\SComm and \EComm) [days={fill=green!90}]
%---------- Phase 6------------------------------
if (equals=\Strike) [days={fill=red!80,rectangle}]
%---------- Phase 7 ------------------------------
if (equals=\ConstatOne,
equals=\ConstatTwo,
equals=\ConstatThree,
equals=\ConstatFour,
equals=\ConstatFive,
) [days={fill=orange!80,rectangle}]
%---------- Phase 8 ------------------------------
if (equals=\FinalValue) [days={fill=red!80,rectangle}]
%---------- Phase 9 ------------------------------
if (equals=\Maturity) [days={fill=blue!80,rectangle}];
\end{tikzpicture}
\end{document}