% Documentation of the persian-calendar package. Build: make doc   (XeLaTeX, font Parisa)
\documentclass[11pt]{article}

\usepackage[a4paper,margin=2.5cm]{geometry}
\usepackage{persian-calendar}
\usepackage{pgffor}
\usepackage{tikz}
\usetikzlibrary{calendar}
\usepackage[colorlinks,linkcolor=blue!50!black,urlcolor=blue!50!black]{hyperref}
\usepackage{xepersian}

\settextfont{Parisa}
\setlatintextfont[Extension=.otf,BoldFont=lmroman10-bold,ItalicFont=lmroman10-italic,BoldItalicFont=lmroman10-bolditalic]{lmroman10-regular}

% --- helpers --------------------------------------------------------------
% \macro|syntax|: heading line for a macro description
\NewDocumentCommand\macro{v}{\par\bigskip\noindent\hbox{\texttt{\bfseries #1}}\par\nopagebreak\smallskip}
% \ex|code|{result}: a call, an arrow and its typeset result (the call is typed twice on purpose)
\NewDocumentCommand\ex{v m}{\par\noindent\hspace*{1em}\texttt{#1}\quad$\Rightarrow$\quad#2}
\newcommand\iso[1]{\lr{#1}}            % numeric dates must stay left to right
\newcommand\pkg[1]{\textsf{#1}}
\newcommand\cs[1]{\texttt{\textbackslash #1}}
\newcommand\gap{\par\smallskip}
\newcount\jd \newcount\wday
\emergencystretch=3em % long macro names in the prose
\renewcommand\thepage{\lr{\arabic{page}}}   % page numbers in Latin digits (the footer is typeset in the Persian font)
% table cells for the name lists: \mc{n} month n, \yc{y} year y; \MROW/\YROW{first} fill a row of four/six
\newcommand\mc[1]{\edef\mm{\number\numexpr#1\relax}\texttt{\mm}\quad\pcalmonthname{\mm}}
\newcommand\yc[1]{\edef\yy{\number\numexpr#1\relax}\texttt{\yy}\quad\pcalyearname{\yy}}
\newcommand\MROW[1]{\mc{#1}&\mc{#1+3}&\mc{#1+6}&\mc{#1+9}}
\newcommand\YROW[1]{\yc{#1}&\yc{#1+3}&\yc{#1+6}&\yc{#1+9}&\yc{#1+12}&\yc{#1+15}}

% The prose uses the Latin font, so the macros that print Persian text switch to the Persian font.
\def\fa@wrap#1{\expandafter\let\csname fa@orig@\string#1\endcsname#1%
  \def#1##1{{\setpersianfont\csname fa@orig@\string#1\endcsname{##1}}}}
\fa@wrap\pdate \fa@wrap\gdate \fa@wrap\pcalmonthname \fa@wrap\pcalgregorianmonthname
\fa@wrap\pcalweekdayname \fa@wrap\pcalweekdayshortname \fa@wrap\pcalyearname

\title{The \pkg{persian-calendar} package}
\author{Javad Razavian\thanks{Source code and bug reports:
  \url{https://github.com/javadr/persian-calendar}}}
\date{Version \pcalendarversion\quad(\pcalendardate)}

\begin{document}
\latin % the text is English (Latin font, left to right); the typeset results are Persian
\leftfootnoterule % the footnote rule on the left, as the text runs left to right

\maketitle

\begin{abstract}\noindent
\pkg{persian-calendar} converts dates between the Persian (Jalali, Solar Hijri) and Gregorian calendars
inside \LaTeX{}. It prints dates with Persian month names, gives day numbers you can do arithmetic
on, and provides Persian month, weekday and year-animal names. It is built on the \pkg{pgfcalendar}
package. The conversions work with any engine; printing the Persian names needs a Unicode
engine and a Persian font, for example XeLaTeX with \pkg{xepersian}.
\end{abstract}

\tableofcontents

% ---------------------------------------------------------------------------
\section{What the package does and does not do}\label{sec:what1}

The package is a date converter and a set of name tables. It provides:
\begin{itemize}
  \item Gregorian $\to$ Jalali and Jalali $\to$ Gregorian conversion, printed as text or as numbers;
  \item Julian day numbers for Jalali dates, so you can add days, subtract dates or loop over days;
  \item Persian names of the Jalali and Gregorian months and of the weekdays;
  \item the animal name of a year in the twelve-animal cycle;
  \item Jalali month grids and year calendars drawn with the \pkg{TikZ} \texttt{calendar} library
    (section~\ref{sec:tikz});
  \item a two-page year planner in the manner of \pkg{yplan} (section~\ref{sec:yplan}).
\end{itemize}
It has no holidays.

\paragraph{Requirements.} The \pkg{pgf} bundle (which contains \pkg{pgfcalendar}) is all the
conversions need, and they work with pdf\LaTeX{}, Xe\LaTeX{} and Lua\LaTeX{}. Only the names (and
so \cs{pdate}, \cs{gdate} and the \texttt{\textbackslash pcal\ldots name} macros) are Persian
text: they are stored as UTF-8 in the source file, so printing them needs an engine and packages that
handle UTF-8 Persian letters, together with a font that has them. \pkg{xepersian} with Xe\LaTeX{} is
what this manual uses, but any setup that can typeset Persian will do. Without one, use the numeric
macros \cs{pisodate} and \cs{gisodate}, which print only digits.

% ---------------------------------------------------------------------------
\section{Loading the package}\label{sec:installation2}

TeX Live and MiKTeX install the package from CTAN, so nothing needs installing by hand.

Load the package in the preamble. The examples here use \pkg{xepersian} for the Persian text and load
\pkg{persian-calendar} before it:
\begin{verbatim}
\usepackage{persian-calendar}
\usepackage{xepersian}
\settextfont{Parisa}
\end{verbatim}
\paragraph{The \texttt{tikz} option.} The Jalali calendars of section~\ref{sec:tikz} need \pkg{TikZ} and
its \texttt{calendar} library. The option \texttt{tikz} loads both:
\begin{verbatim}
\usepackage[tikz]{persian-calendar}
\end{verbatim}
Without it the package loads only \pkg{pgf} and \pkg{pgfcalendar}, so a document that only converts
dates loads faster. Loading \pkg{tikz} or the library yourself as well does no harm.

% ---------------------------------------------------------------------------
\section{Quick start}\label{sec:quick3}

\begin{verbatim}
\pdate{2015-03-21}          % Gregorian date in, Jalali text out
\gdate{1394-01-01}          % Jalali date in, Gregorian text out
\pisodate{2015-03-21}       % Gregorian in, Jalali as DD/MM/YYYY
\gisodate{1394-01-01}       % Jalali in, Gregorian as DD/MM/YYYY
\end{verbatim}
which print:
\ex|\pdate{2015-03-21}|{\pdate{2015-03-21}}
\ex|\gdate{1394-01-01}|{\gdate{1394-01-01}}
\ex|\pisodate{2015-03-21}|{\iso{\pisodate{2015-03-21}}}
\ex|\gisodate{1394-01-01}|{\iso{\gisodate{1394-01-01}}}
\gap
Today's date, in the Jalali calendar, is \cs{pdate}\texttt{\{\cs{year}-\cs{month}-\cs{day}\}}, which
prints \pdate{\year-\month-\day}.

% ---------------------------------------------------------------------------
\section{Date conversion}\label{sec:date4}

All four macros take one argument, a date written \texttt{Y-M-D}: a year, a month number and a day
number joined by hyphens. The month and day may have a leading zero or not
(\texttt{2015-3-21} and \texttt{2015-03-21} are the same).

\macro|\pdate{Y-M-D}|
The argument is a \emph{Gregorian} date. Prints the \emph{Jalali} date as ``day month-name year'',
for example \pdate{2024-03-20}.

\macro|\gdate{Y-M-D}|
The argument is a \emph{Jalali} date. Prints the \emph{Gregorian} date as ``day month-name year'',
using the Persian transliteration of the Gregorian month, for example \gdate{1403-01-01}.

\macro|\pisodate{Y-M-D}|
Like \cs{pdate} (Gregorian in, Jalali out) but prints numbers: day, month and year, each day and
month padded to two digits and separated by a slash, so \iso{\pisodate{2024-03-20}}. Note the order:
this is day/month/year, not the ISO order year-month-day.

\macro|\gisodate{Y-M-D}|
Like \cs{gdate} (Jalali in, Gregorian out) but prints numbers in the same day/month/year form, for
example \iso{\gisodate{1403-01-01}}.

\paragraph{Leap years.} Esfand, the last Jalali month, has 30 days in a leap year:
\ex|\pdate{2025-03-20}|{\pdate{2025-03-20}}
\ex|\gdate{1403-12-30}|{\gdate{1403-12-30}}
\ex|\gdate{1404-12-30}|{\gdate{1404-12-30}}
The last line is an invalid date, since 1404 is not a leap year; the package does not check this
(section~\ref{sec:limitations9}).

\paragraph{Wrap the numeric forms.} Digits in Persian text are reordered by the bidirectional
algorithm. To keep \cs{pisodate} and \cs{gisodate} in day/month/year order inside Persian text, put
them in an \cs{lr} box, as this document does.

% ---------------------------------------------------------------------------
\section{Day numbers and date arithmetic}\label{sec:day5}

The conversion macros above cannot add days. For that, the package works with Julian day numbers as
defined by \pkg{pgfcalendar}: whole days counted from a fixed origin, so subtracting two numbers gives
the number of days between two dates.

\macro|\pcaldatetojulian{Y-M-D}{\count}|
Stores the day number of the \emph{Jalali} date \texttt{Y-M-D} in the count register \cs{count}. Append
\texttt{+N} to the date to add \texttt{N} days first: \texttt{1394-01-01+10} is ten days after
1 Farvardin 1394.

\macro|\pcaljuliantodate{\count}{\y}{\m}{\d}|
Converts the day number in \cs{count} back to a \emph{Jalali} date and puts the year, month and day
into the macros \cs{y}, \cs{m} and \cs{d} (you may choose other names).

\begin{verbatim}
\newcount\jd
\pcaldatetojulian{1394-01-01+10}\jd
\pcaljuliantodate\jd\y\m\d
\number\y-\number\m-\number\d
\end{verbatim}
\pcaldatetojulian{1394-01-01+10}\jd%
\pcaljuliantodate\jd\y\m\d%
prints \iso{\number\y-\number\m-\number\d}.

\paragraph{Read \cs{y}, \cs{m}, \cs{d} immediately.} After \cs{pcaljuliantodate} the three macros
are aliases of the package's internal result registers, not copies. Any later conversion
(\cs{pdate}, \cs{gisodate}, and so on) changes them. If you need the values later, store them in your
own counters first: \texttt{\cs{newcount}\cs{myyear}\ \cs{myyear=\cs{y}}}.

\macro|\pcaldaysbetween{Y-M-D}{Y-M-D}{\count}|
Stores the number of days from the first Jalali date to the second in \cs{count}; it is negative when the
second date is earlier. Both dates may end in an offset, as with \cs{pcaldatetojulian}.
\begin{verbatim}
\newcount\n
\pcaldaysbetween{1403-01-01}{1404-01-01}{\n}
\number\n
\end{verbatim}
\pcaldaysbetween{1403-01-01}{1404-01-01}{\jd}%
prints \number\jd{} (1403 is a leap year).

\paragraph{Offsets across a year end.} Day arithmetic knows about leap years:
\pcaldatetojulian{1403-12-29+1}\jd\pcaljuliantodate\jd\y\m\d%
1403-12-29 plus one day is \iso{\number\y-\number\m-\number\d}, because 1403 is a leap year;
\pcaldatetojulian{1403-12-29+2}\jd\pcaljuliantodate\jd\y\m\d%
plus two days is \iso{\number\y-\number\m-\number\d}.

\paragraph{Counts used internally.} \cs{pcaldatetojulian} uses \cs{count1}, \cs{count2},
\cs{count3} and \cs{count8} as scratch registers. Do not keep values in those.

% ---------------------------------------------------------------------------
\section{Names}\label{sec:names6}

\macro|\pcalmonthname{n}|
Persian month name, \texttt{n} from 1 to 12. An argument outside this range prints nothing.
\ex|\pcalmonthname{1}|{\pcalmonthname{1}}
\gap
All twelve, in order:\gap
\gap
\begin{tabular}{llll}
\MROW{1}\\
\MROW{2}\\
\MROW{3}
\end{tabular}

\macro|\pcalgregorianmonthname{n}|
Persian transliteration of the Gregorian month name, \texttt{n} from 1 to 12.
\ex|\pcalgregorianmonthname{3}|{\pcalgregorianmonthname{3}}

\macro|\pcalweekdayname{n}|
Weekday name, \texttt{n} from 0 to 6, where \textbf{0 is Saturday} (the first day of the Persian
week) and 6 is Friday.
\gap
\foreach \w in {0,...,6}{\texttt{\w}~\pcalweekdayname{\w}\quad}

\macro|\pcalweekdayshortname{n}|
One-letter weekday abbreviation, same numbering.
\gap
\foreach \w in {0,...,6}{\texttt{\w}~\pcalweekdayshortname{\w}\quad}

\macro|\pcalyearname{year}|
Name of a Jalali year in the twelve-animal cycle. \texttt{year} must be between 0 and 2099;
other values print nothing.
\ex|\pcalyearname{1403}|{\pcalyearname{1403}}
\gap
The twelve animals in order, starting from year 1380:\gap
\gap
{\setlength\tabcolsep{4pt}% six columns fit the text width
\begin{tabular}{llllll}
\YROW{1380}\\
\YROW{1381}\\
\YROW{1382}
\end{tabular}}

\macro|\pcalweekday{Y-M-D}{\count}|
Stores the weekday of a Jalali date in \texttt{\textbackslash count}, numbered like
\cs{pcalweekdayname}: 0 is Saturday, 6 is Friday. As with \cs{pcaldatetojulian}, the date may end in an
offset in days, and macros in it are expanded.
\begin{verbatim}
\newcount\wday
\pcalweekday{1403-01-01}{\wday}      % \wday = 4, Wednesday
\pcalweekday{1403-01-01+10}{\wday}   % ten days later: 0, Saturday
\end{verbatim}

\macro|\pcaldateweekdayname{Y-M-D}|
Prints the weekday name of a Jalali date: \cs{pcalweekdayname} of \cs{pcalweekday}.
\ex|\pcaldateweekdayname{1403-01-01}|{\pcaldateweekdayname{1403-01-01}}

% ---------------------------------------------------------------------------
\section{Calendars with TikZ}\label{sec:tikz}

The \pkg{TikZ} \texttt{calendar} library draws calendars with \cs{calendar}, but it only knows Gregorian
months. The package adds a few keys that make it lay out Jalali months instead. They need \pkg{tikz} and
the library, which the \texttt{tikz} option loads (section~\ref{sec:installation2}):
\begin{verbatim}
\usepackage[tikz]{persian-calendar}
...
\tikz\calendar[jalali dates=1405-01-01 to 1405-03-last,
               jalali week list, day xshift=-2.2em, day yshift=2.5ex,
               jalali month label above centered]
  if (Friday) [red] if (jalali equals=1-13) [blue];
\end{verbatim}
\begin{center}
\tikz\calendar[jalali dates=1405-01-01 to 1405-03-last,
               jalali week list, day xshift=-2.2em, day yshift=2.5ex,
               jalali month label above centered]
  if (Friday) [red] if (jalali equals=1-13) [blue];
\end{center}

\macro|jalali dates=Y-M-D to Y-M-D|
The range to draw, as Jalali dates. The day can be \texttt{last}, the last day of that month (29 or 30 for
Esfand, depending on the leap year). It sets the library's \texttt{dates} key, so the two must not be mixed.

\macro|jalali|
Switches the calendar to Jalali dates. The day number and the month label print the Jalali day and the
Persian month name with the year (change them with \texttt{day text} and \texttt{month text}). Inside the
calendar, the test \texttt{day of month=}$n$ means the Jalali day, so the library's
\texttt{month label \ldots} styles fire on the first of each Jalali month. For every day,
\cs{pcalcurrentyear}, \cs{pcalcurrentmonth}, \cs{pcalcurrentday} hold the Jalali date and
\cs{pcalcurrentweekday} the weekday counted from Saturday${}=0$ (like \cs{pcalweekdayname}), so
they can be used in \texttt{day code}.

\macro|jalali week list|
Like the library's \texttt{week list}, but for Jalali months: \texttt{jalali} is included, a week runs from
Saturday to Friday and a new month starts a new block. With the default positive \texttt{day xshift}
Saturday is on the left; a negative \texttt{day xshift}, as above, puts it on the right.

\macro|jalali month label above centered|
Like the library's \texttt{month label above centered}, which places the label with a fixed \texttt{1.5ex}
offset and so leaves it slightly off centre. This one measures a two-digit day (\texttt{30}) in the current
font and adds the inner sep of the day nodes, so the label is centred over the week at any font size.
It assumes the library's default \texttt{every day} anchor (\texttt{base east}).

\macro|jalali week columns|
The other way round, as in \pkg{calxxxx-yyyy}: one row per weekday, Saturday on top, and a new column after
each Friday, so a month is four to six columns wide. A negative \texttt{day xshift} puts the first week on
the right. \texttt{jalali day boxes} completes the first and last columns, \texttt{jalali weekday initials}
puts the initials in a column beside the month, and \texttt{jalali month label above centered} centres over
the month's own number of columns. The sample \texttt{persian-calendar-years.tex} uses it to print a range of
years, nine to an A4 page: set \cs{FirstYear} and \cs{LastYear} at its top.

\macro|jalali day boxes|
Draws every day as a box one day step wide (\texttt{day xshift}) and high (\texttt{day yshift}), so the boxes
join into a grid. With \texttt{jalali week list}, empty boxes fill the days before the first and after the last
day of each month (or of the range), so every month is a full rectangle of whole weeks. The text height and depth are fixed in \texttt{ex}, so all rows are level at any font size.
\texttt{jalali month label above centered} then centres over the boxes. To fill some days, append to their
\texttt{every day} style, as in the example below; a plain \texttt{fill=} in \texttt{if (\ldots)} does not
reach the box.

\macro|jalali weekday initials|
Adds a row of weekday initials (\pcalweekdayshortname{0}, \pcalweekdayshortname{1}, \ldots,
\pcalweekdayshortname{6}, from \cs{pcalweekdayshortname}) one row above each month, in boxes
when \texttt{jalali day boxes} is on. It works with \texttt{jalali week list}, and the month label moves
up above it. Style the initials with \texttt{every jalali weekday}, for example
\texttt{every jalali weekday/.style=\{font=\textbackslash bfseries\}}.

With either key, a new month starts at least three rows (four with initials) below the previous one,
however small \texttt{month yshift} is, so an unfinished last week never runs into the next label.
\begin{verbatim}
\tikz\calendar[jalali dates=1405-01-01 to 1405-02-last,
  jalali week list, jalali day boxes, jalali weekday initials,
  day xshift=-0.9cm, day yshift=0.7cm,
  jalali month label above centered]
  if (Friday) [red, every day/.append style={fill=red!10}];
\end{verbatim}
\begin{center}
\tikz\calendar[jalali dates=1405-01-01 to 1405-02-last,
  jalali week list, jalali day boxes, jalali weekday initials,
  day xshift=-0.9cm, day yshift=0.7cm,
  jalali month label above centered]
  if (Friday) [red, every day/.append style={fill=red!10}];
\end{center}

\macro|jalali equals=M-D|
A date test that matches one Jalali month and day in every year, for example \texttt{jalali equals=1-1}
for Nowruz. It can be used in \texttt{if (\ldots)} and with \cs{pgfcalendarifdate}, also outside
\texttt{jalali} calendars, as can \texttt{jalali day of month=}$n$.

\paragraph{Other layouts.} \texttt{day list downward}, \texttt{day list upward}, \texttt{day list right} and
\texttt{day list left} work together with \texttt{jalali}, because they only test \texttt{day of month=1}.
The library's \texttt{week list} and \texttt{month list} use the Gregorian weekday and day, so use
\texttt{jalali week list} instead.

\paragraph{A year by season.} Draw one calendar per month with \cs{foreach} and place each with
\texttt{at}: the month gives the column within its season, the season the row. The minus sign in
\texttt{-\textbackslash col} puts the later months further left, so the page reads right to left; drop it,
and the minus of \texttt{day xshift}, for left to right. The horizontal step must be wider than seven days,
the vertical one taller than six weeks and the label. \texttt{1405-\textbackslash m-01} works because the
hyphens are written out and \cs{m} is only read as a number; a single macro holding the whole date would not. All months are in the same year, so \texttt{month text}
replaces the default label (month and year) with the month name alone; put it after \texttt{jalali week list},
which sets its own.
\begin{verbatim}
\begin{tikzpicture}
\foreach \m in {1,...,12} {
  \pgfmathtruncatemacro\col{mod(\m-1,3)}% month within the season
  \pgfmathtruncatemacro\row{div(\m-1,3)}% season
  \calendar at (-\col*5.4cm, -\row*4.6cm)
    [jalali dates=1405-\m-01 to 1405-\m-last, jalali week list,
     day xshift=-0.7cm, day yshift=0.5cm,
     jalali month label above centered,
     month text={\pcalmonthname{\pcalcurrentmonth}}]
    if (Friday) [red];
}
\end{tikzpicture}
\end{verbatim}
\begin{center}
\begin{tikzpicture}
\foreach \m in {1,...,12} {
  \pgfmathtruncatemacro\col{mod(\m-1,3)}% month within the season
  \pgfmathtruncatemacro\row{div(\m-1,3)}% season
  \calendar at (-\col*5.4cm, -\row*4.6cm)
    [jalali dates=1405-\m-01 to 1405-\m-last, jalali week list,
     day xshift=-0.7cm, day yshift=0.5cm,
     jalali month label above centered,
     month text={\pcalmonthname{\pcalcurrentmonth}}]
    if (Friday) [red];
}
\end{tikzpicture}
\end{center}

\paragraph{Calendars for a range of years.} The \pkg{calxxxx-yyyy} document on CTAN prints Gregorian
calendars for a range of years, nine years to a page, each year as four rows of three months and each month
as a column per week and a row per weekday. \cs{pcalyear} and \cs{pcalyears} draw the same layout for
Jalali years, with \texttt{jalali week columns}. Like the keys above they need \pkg{TikZ} and its
\texttt{calendar} library (the \texttt{tikz} option); without them they stop with an error that says so.

\macro|\pcalyear{year}|
Draws one Jalali year as a \texttt{tikzpicture}: the year as title, then four rows of seasons, three months
each, right to left, with the Fridays in red. It is sized for nine years to an A4 page, 0.3\,cm per day.

\macro|\pcalyears{first}{last}|
Draws the years from \texttt{first} to \texttt{last}, three to a row, on as many pages as they need. The
sample \texttt{persian-calendar-years.tex}, which comes with the package, is the Jalali counterpart of
\pkg{calxxxx-yyyy}: it calls \cs{pcalyears} with \cs{FirstYear} and \cs{LastYear}, set at its top to
\texttt{1405} and \texttt{1413}.

\paragraph{Styles.} Four \pkg{TikZ} styles change the look; set them with \cs{tikzset}:
\begin{itemize}
  \item \texttt{every pcal year}: the picture of a year (default font \verb|\tiny|);
  \item \texttt{every pcal year title}: the year at the top (default font \verb|\footnotesize\bfseries|);
  \item \texttt{every pcal month}: added to the options of each month's \cs{calendar}, after the package's own;
  \item \texttt{pcal friday}: the Fridays, \texttt{red} by default.
\end{itemize}
The first three are empty; the fonts above are set before them. For example, this draws the Fridays in
blue:
\begin{verbatim}
\tikzset{pcal friday/.style={blue}}
\end{verbatim}
This is \verb|\pcalyear{1405}|:
\begin{center}
\pcalyear{1405}
\end{center}

% ---------------------------------------------------------------------------
\section{A year planner}\label{sec:yplan}

The \pkg{yplan} package on CTAN prints a vertical year planner: all the days of a year on two A4 pages,
six months to a page, with a column per month and a row per day. \cs{pcalplanner} does the same for a Jalali
year. It is an ordinary \texttt{tabular}, so it needs neither \pkg{TikZ} nor any package beyond the ones
that print Persian.

\macro|\pcalplanner{year}|  \quad\texttt{\bfseries\textbackslash pcalplanner*\{year\}}
Typesets Jalali \texttt{year} on two pages: Farvardin to Shahrivar, then Mehr to Esfand. Each page starts
with \cs{clearpage} and has page style \texttt{empty}. Above the table is the year, followed by
\cs{pcalplannerleapyear} (``\rl{\setpersianfont\pcalplannerleapyear}'') in a leap year. Down the side are the weekday names; the
rows are aligned on the weekday, so a row is the same weekday in every month. Weeks run Saturday to
Friday and a double rule follows every Friday. As in \pkg{yplan}, only the cells that hold a day are
ruled, and each page has as many rows as its months need (at most 37). The six month columns share the
line width that the weekday column and the rules leave, so the page margins set their width. Under
\pkg{xepersian} the table runs right to left: the weekday column is on the right, then Farvardin.
The year may be a macro.
\begin{verbatim}
\documentclass{article}
\usepackage[a4paper,margin=1.2cm]{geometry}
\usepackage{persian-calendar}
\usepackage{xepersian}
\settextfont{Parisa}
\begin{document}
\pcalplanner{1405}
\end{document}
\end{verbatim}
The sample \texttt{persian-calendar-planner.tex}, which comes with the package, prints such planners
with the Fridays shaded and a few notes.

\paragraph{Week numbers.} \cs{pcalplanner} prints the number of the week in each Saturday cell, on the far
side of the cell from the day (the left under \pkg{xepersian}), and in the cell of 1~Farvardin when that is
not a Saturday; \cs{pcalplanner*} leaves the week numbers out. There is no official rule for numbering the
weeks of the Jalali year, so the package moves ISO~8601 to the Persian week. ISO makes week~1 the week
that holds the year's first Thursday, the middle day of a Monday-to-Sunday week. The middle day of a
Saturday-to-Friday week is Tuesday, so here week~1 is the week that holds the first Tuesday of the year,
that is the week holding 4~Farvardin. As in ISO, every week runs from Saturday to Friday, and a year has
52 weeks, or 53 when 1~Farvardin is a Tuesday, or a Monday in a leap year. 1--3~Farvardin belong to the
last week of the old year when 1~Farvardin is a Wednesday, Thursday or Friday: 1~Farvardin 1403, a
Wednesday, is in week~53 of 1402. The last days of Esfand belong to week~1 of the new year when the next
1~Farvardin is a Sunday, Monday or Tuesday. \cs{pcalplannerweeknumber} prints the number, which it takes as
its argument, in \cs{scriptsize}; redefine it to change the look.

\paragraph{Adjusting the layout.} As in \pkg{yplan}, these can be redefined with \cs{renewcommand}:
\begin{itemize}
  \item \cs{pcalplannerdaystrut}: sets the height of the day rows; \verb|\rule{0pt}{12pt}| by default.
    Make it taller or shorter to fill the page.
  \item \cs{pcalplannermonthstrut}: the same for the row of month names.
  \item \cs{pcalplannerleapyear}: the leap-year label.
\end{itemize}

\macro|\pcalplannernote{M-D}{text}|  \quad\texttt{\bfseries\textbackslash pcalplannernote\{Y-M-D\}\{text\}}
Adds a note to a day, as on a wall calendar: \cs{pcalplanner} puts \cs{pcalplannermark} (a star) after the
day in its cell and lists the notes of each page under its table, in date order and grouped by month: each
month once, followed by its days and their notes, as in ``Farvardin: 1)~\ldots{} 13)~\ldots{}\quad
Khordad: 14)~\ldots''. A date without a year
(\texttt{M-D}) is for every year, which suits holidays; one with a year (\texttt{Y-M-D}) only for that
year. A day may have several notes; it is listed once, with its texts joined by a comma, and the
notes for every year come first. Give the notes before
\cs{pcalplanner}, for example in the preamble. A note for 30~Esfand appears only in a leap year.
\begin{verbatim}
\pcalplannernote{1-1}{Nowruz}
\pcalplannernote{1-13}{Nature Day}
\pcalplannernote{1405-7-1}{First day of autumn 1405}
\end{verbatim}
These macros set the look of the list; redefine them, and \cs{pcalplannermark}, to change it:
\begin{itemize}
  \item \cs{pcalplannernotesfont}: the font of the list, \cs{footnotesize};
  \item \cs{pcalplannernotemonth}\texttt{\{year\}\{month\}}: the heading of a month, its name in bold and a colon;
  \item \cs{pcalplannernoteday}\texttt{\{year\}\{month\}\{day\}}: the label of a day, \texttt{day)};
  \item \cs{pcalplannernotemonthsep}, \cs{pcalplannernotesep}, \cs{pcalplannernotetextsep}: the space between
    months (\cs{qquad}), between days (\cs{quad}) and between the texts of one day (a Persian comma).
\end{itemize}
The notes take room under the table: with many of them, make \cs{pcalplannerdaystrut} shorter so that
each page still fits.

\macro|\pcalplannercell{year}{month}{day}{weekday}|
Typesets one day cell. \cs{pcalplanner} calls it for every day with the Jalali year, month and day, and the
weekday numbered as \cs{pcalweekdayname} does (0 is Saturday, 6 is Friday). By default it prints
the day number. Redefine it to colour, mark or annotate days; empty cells do not call it. This one
shades the Fridays and prints 1 Farvardin in red:
\begin{verbatim}
\usepackage[table]{xcolor}
\providecommand\UseMathForPositioningText{}
...
\renewcommand\pcalplannercell[4]{%
  \ifnum#4=6 \cellcolor{gray!20}\fi
  \ifnum\numexpr#2*100+#3=101 \textcolor{red}{#3}\else#3\fi}
\end{verbatim}
\cs{cellcolor} comes from \pkg{colortbl}, which the \texttt{table} option of \pkg{xcolor} loads. The
\cs{providecommand} line works around a bug in \pkg{bidi} (section~\ref{sec:limitations9}). Use
\cs{textcolor} rather than \cs{color} in a cell: \cs{color} at the start of a cell moves the number down
a line. The cell is a paragraph column, so longer text, such as a holiday name, wraps inside it.

% ---------------------------------------------------------------------------
\section{Recipes}\label{sec:recipes7}

\paragraph{A list of consecutive days.} Typeset the 5 days after 1 Farvardin 1403 with a loop. Each date
is converted and printed right away, because the result macros are overwritten by the next
conversion:
\begin{verbatim}
\newcount\jd
\foreach \x in {0,...,4}{%
  \pcaldatetojulian{1403-01-01+\x}\jd
  \pcaljuliantodate\jd\y\m\d
  \number\y-\number\m-\number\d\par
}
\end{verbatim}
\foreach \x in {0,...,4}{%
  \pcaldatetojulian{1403-01-01+\x}\jd
  \pcaljuliantodate\jd\y\m\d
  \par\noindent\hspace*{1em}\iso{\number\y-\number\m-\number\d}%
}
\par\medskip
Using \texttt{\cs{x}} inside \cs{pcaldatetojulian} works, because that macro expands its argument.

\paragraph{Declare registers once.} \cs{newcount} inside a loop allocates a new register at every
iteration and eventually fails with ``No room for a new \cs{count}''. Declare your counters before the
loop.

% ---------------------------------------------------------------------------
\section{How it works}\label{sec:how8}

The conversions are plain TeX register arithmetic, with no external program and no Lua. Two internal
macros do all the work. Every public macro calls one of them and then prints or copies the result
registers.

\begin{description}
  \item[\texttt{\textbackslash pcal@gregoriantojalali\{Y-M-D\}}] Gregorian to Jalali. It first decides
    whether the Gregorian year is a leap year, builds the month-length tables of both calendars, and
    counts the days from the start of the Gregorian year to the date. It then walks the Jalali month
    lengths until that day count is used up. The Jalali leap year rule is the common
    \emph{33-year cycle}: eight leap years in every 33.
  \item[\texttt{\textbackslash pcal@jalalitogregorian\{Y-M-D\}}] Jalali to Gregorian. It computes the
    number of days since a fixed epoch from the year (365 days per year, plus 8 leap days per 33 years,
    plus the leap days of the partial cycle), adds the days of the preceding months, and then splits
    that total into 400-year, 100-year, 4-year and 1-year Gregorian blocks.
\end{description}

\paragraph{Result registers.} Jalali results are in \cs{pcal@y}, \cs{pcal@m}, \cs{pcal@d}. Gregorian
results are in \cs{pcal@gy}, \cs{pcal@gm}, \cs{pcal@gd}. The leap flags are \cs{ifpcal@leap}
(Gregorian) and \cs{ifpcal@kabiseh} (Jalali). The month lengths are held in registers whose names end in
roman numerals (\cs{pcal@latini} to \cs{pcal@latinxii} and \cs{pcal@persiani} to
\cs{pcal@persianxiii}). Dey appears twice: the first slot is the part of Dey left in the Gregorian year, the last is
the whole month, which is why there are thirteen.

\paragraph{Julian day bridge.} \cs{pcaldatetojulian} converts the Jalali date to Gregorian with the
Jalali-to-Gregorian macro above and hands the result to \cs{pgfcalendardatetojulian}.
\cs{pcaljuliantodate} does the reverse: \cs{pgfcalendarjuliantodate} gives a Gregorian date, which the
Gregorian-to-Jalali macro turns into the Jalali date.

\paragraph{Year names.} The twelve animals repeat every 12 years. A second, three-step shift is applied
once per century, so that year 0 starts the cycle at a different animal than year 100. This is why the
macro stops at 2099.

\paragraph{No register leaks.} All registers are allocated once when the package loads, so any number of
conversions can be made in one document. A test in the repository (\texttt{leaks.lvt}) checks this.

\paragraph{TikZ calendars.} The keys of section~\ref{sec:tikz} are defined with \cs{pgfkeys} when the
package loads, so they need no \pkg{TikZ} until they are used. \texttt{jalali dates} converts both ends to
Gregorian and passes them to the library's \texttt{dates} key; \texttt{last} becomes the first day of the
next Jalali month with a \texttt{+-1} offset. \texttt{jalali} puts a call that sets \cs{pcalcurrentyear}
and the others in front of every day, ahead of the library's own per-day code, and redefines the
\texttt{day of month} test for that calendar only. The conversions are run inside a group, because
\pkg{pgfcalendar} walks the days with \cs{loop} and the conversions use \cs{loop} too.

\paragraph{The year planner.} For each page \cs{pcalplanner} converts only the 1st of each of its six months
(and of the month after) to a day number, through \cs{pcaldatetojulian}'s machinery; their
differences are the month lengths, and the weekday of each 1st gives the month's first row. The rows are
then written into a token register, one cell per month with a call to \cs{pcalplannercell} in each cell that
holds a day, together with the \cs{cline}s under them, and the register is put into the
\texttt{tabular}. The rows are built by recursion rather than \cs{loop}, for the reason above.

% ---------------------------------------------------------------------------
\section{Limitations and known issues}\label{sec:limitations9}

\begin{itemize}\sloppy % long code names cannot be hyphenated
  \item \textbf{No input checking.} A month 13, day 40 or malformed string gives wrong output or a TeX
    error, not a package message.
  \item \textbf{Literal dates only.} The date argument of \cs{pdate}, \cs{gdate}, \cs{pisodate} and
    \cs{gisodate} is split at the hyphens as it stands; a macro holding a date is not expanded. Write
    \cs{pdate}\texttt{\{2015-03-21\}}, not \cs{pdate}\cs{mydate}. (\cs{pcaldatetojulian} does
    expand its date.)
  \item \textbf{Approximate Jalali leap rule.} The 33-year rule is an arithmetic approximation of the
    official calendar, which is defined by astronomical observation. The two agree for the years in
    ordinary use, but not necessarily for all years. For distant years, check against an authoritative
    table.
  \item \textbf{A known crash.} \cs{pcal@jalalitogregorian}\texttt{\{1279-10-11\}} stops with ``Missing
    number, treated as zero''; neighbouring dates work. The cause has not been found.
  \item \textbf{Nested loops.} The conversions use \cs{loop} from the \LaTeX{} kernel internally. A
    \cs{loop}\ldots\cs{repeat} of your own that calls them must run its body inside a group
    (\cs{begingroup}\ldots\cs{endgroup}), otherwise it stops after one pass. \cs{foreach} is not affected.
  \item \textbf{Shared registers.} Every conversion overwrites the result registers, as described in
    section~\ref{sec:day5}.
  \item \textbf{Year names} work for 0 to 2099 only.
  \item \textbf{TikZ layouts.} Only \texttt{jalali week list}, \texttt{jalali week columns} and the
    \texttt{day list} styles follow Jalali months; the library's \texttt{week list} and \texttt{month list}
    stay Gregorian.
  \item \textbf{\texttt{jalali dates} and \texttt{dates}} set the same range, so the later one wins. The
    dates of \texttt{jalali dates} must be literal, like those of \cs{pdate}.
  \item \textbf{Boxes and labels assume right-aligned days.} \texttt{jalali day boxes} and
    \texttt{jalali month label above centered} expect the library's default \texttt{every day} anchor
    (\texttt{base east}). The initials are one style for all seven days, so a Friday initial cannot be
    coloured on its own.
  \item \textbf{TikZ internals.} \texttt{jalali} adds its code to the library's internal macro
    \cs{tikz@before@day}. A future \pkg{TikZ} that renames it would break the Jalali calendars; the
    regression test \texttt{tikz.lvt} would catch it.
  \item \textbf{Shading planner cells with \pkg{xepersian}.} Loading \pkg{colortbl} (for example with
    \verb|\usepackage[table]{xcolor}|) together with \pkg{xepersian} stops at the first table with
    ``Undefined control sequence \cs{UseMathForPositioningText}''. \pkg{bidi}'s adaptation of
    \pkg{array} uses this macro, which current versions of \pkg{array} no longer define. Until \pkg{bidi}
    is fixed, put \verb|\providecommand\UseMathForPositioningText{}| in the preamble.
  \item \textbf{The planner is A4 portrait by default.} \cs{pcalplanner} does not change the page size or the
    margins; set them with \pkg{geometry}, and the row height with \cs{pcalplannerdaystrut}.
  \item \textbf{Do not redefine \cs{wd}.} \cs{newcount}\cs{wd} or similar replaces a \TeX{} primitive that
    \pkg{TikZ} needs, and stray text such as ``\texttt{==0pt}'' appears in the pictures.
\end{itemize}

% ---------------------------------------------------------------------------
\section{Version history}\label{sec:version11}

\begin{description}\sloppy % long code names cannot be hyphenated
  \item[0.78 (2026-11-06)] \cs{pcalplannernote}: notes in the year planner, marked in the cells and listed under
    each page by month, as on a wall calendar.
  \item[0.77 (2026-11-06)] Week numbers in \cs{pcalplanner}, by ISO~8601 moved to Saturday weeks; \cs{pcalplanner*}
    leaves them out.
  \item[0.76 (2026-11-06)] Manuals: the Installation section is now ``Loading the package''.
  \item[0.75 (2026-11-06)] \cs{pcaldaysbetween}: the number of days between two Jalali dates.
  \item[0.74 (2026-11-06)] \cs{pcalweekday} and \cs{pcaldateweekdayname}: the weekday of a Jalali date.
  \item[0.73 (2026-11-06)] The \texttt{tikz} option, which loads \pkg{TikZ} and its \texttt{calendar} library.
  \item[0.72 (2026-11-05)] \cs{pcalyear} and \cs{pcalyears}: year calendars in the manner of
    \pkg{calxxxx-yyyy}, with styles for the year, its title, the months and the Fridays.
  \item[0.71 (2026-11-05)] Shorter names: \cs{pcal\ldots} instead of \cs{pcalendar\ldots}; the old names still
    work.
  \item[0.7 (2026-11-05)] A year planner in the manner of \pkg{yplan}: \cs{pcalplanner}, and
    \cs{pcalplannercell} to colour or annotate its days. The sample
    \texttt{persian-calendar-planner.tex}.
  \item[0.62 (2026-11-04)] \texttt{jalali week columns} and the sample \texttt{persian-calendar-years.tex}.
  \item[0.61 (2026-11-03)] \texttt{jalali day boxes} (a grid of boxes) and \texttt{jalali weekday initials}.
  \item[0.6 (2026-11-03)] Renamed from \pkg{pcalendar} to \pkg{persian-calendar} at the request of CTAN (file
    and package names only, the macros keep their names). Jalali month grids with the \pkg{TikZ}
    \texttt{calendar} library (section~\ref{sec:tikz}). License stated as LPPL 1.3c everywhere.
  \item[0.51 (2026-11-01)] Documentation only: the manuals now say that only printing the Persian names
    needs a Unicode engine and a Persian font; the Persian manual was rewritten.
  \item[0.5 (2026-11-01)] Fixed the register leak (several \cs{newcount} per call) and the undeclared
    month-length register; added this manual and
    \cs{pcalendardate}/\cs{pcalendarversion}.
  \item[0.4 (2023-11-07)] Ready for CTAN.
  \item[0.3 (2015-08-14)] Animal name of a Jalali year, 0 to 2099.
  \item[0.2 (2015-08-09)] Jalali to Gregorian conversion.
  \item[0.1 (2015-07-25)] Initial version.
\end{description}

\end{document}
