User’s Guide to the Calendar package^{∗}

Frank G. Bennett, Jr.^{†}

February 6, 1997

Abstract This package provides tools for creating customized calendars using

L^{A}TEX 2ε.

1 Introduction

This packages creates a macro, \everyday which accepts four arguments. The first two are dates of the form YYYY/MM/DD. The third is a template that should generate a document of some kind. The templates are generated once for each date in the range of dates defined by the first and second arguments, inclusive. Within the templates use \theweekday to get the day of the week, \theyear to get the year less the leading 19, \themonth to get the name of the month, \theday to get the current day. For an application calling on these macros, see the timesht package, also on CTAN.

2 The Macros

2.1 Higher Math Option

 1 \DeclareOption{highermath}{%

Convert from Julian date and time in o long date (in local time)

 2 \def\JDTtoL{\advance\date by500
 3 \advance\date by\timezone\divide\date by1000}

Trigonometric functions

 4 \def\sintable#1{\ifcase #1 0\or100\or199
 5 \or296\or389\or479\or565\or644\or717
 6 \or783\or841\or891\or932\or964\or985
 7 \or997\or1000\or992\or974\or946\or909
 8 \or863\or808\or746\or675\or598\or516
 9 \or427\or335\or239\or141\or42\or-58
10 \or-158\fi}

Reduces modulo 2\pi (requires positive argument theta): theta := theta

MOD 2\pi, where theta = count1*10^(-3)

∗This file is version number v0.02. It was last revised on 1996/11/11.

†The code contained in this file is simply a recasting of the calendar macros for TEX that I found on CTAN into L^{A}TEX 2ε. The TEX macros work quite well, but lack any documentation.

Their provenance is also a mystery. If anyone can tell me who wrote them, I will gladly include an acknowledgement in this documentation.

11 \def\twopimod{\count2 =\count1
12 \divide\count2 by6284 \count3 =1853
13 \count4 =6283\multiply\count3  by\count2
14 \multiply\count4  by\count2
15 \divide\count3  by10000
16 \advance\count3  by\count4
17 \advance\count1  by-\count3}
v := sin(theta), where v = count4*10^(-3); theta = count1*10^(-3) theta

is reduced MOD 2\pi to be 0<=theta<2\pi by \TWOPIMOD, then linear interpolation is performed using \SINTABLE.

18 \newif\ifsign
19 \def\Sin{
20 \ifnum\count1<0 \signtrue
21 \count1=-\count1\else \signfalse\fi
22 \loop\ifnum\count1>6284\twopimod\repeat
23 \ifnum\count1>3142
24 \advance\count1 by-3142
25 \ifsign\signfalse\else\signtrue\fi\fi
26 \multiply\count1  by10 \count3 =\count1
27 \divide\count3  by1000 \count2 =\count3
28 \multiply\count3  by1000
29 \advance\count3  by-\count1
30 \count5 =\sintable{\count2 }
31 \count4 =\count5\advance\count2  by1
32 \advance\count4  by -\sintable{\count2 }
33 \multiply\count4  by\count3
34 \divide\count4  by1000
35 \advance\count4  by\count5
36 \ifsign\count4 =-\count4 \fi}
v := cos(theta), where v = count4*10^(-3); theta = count1*10^(-3). \SIN

is evaluated on pi/2-theta.

37 \def\Cos{\advance\count1  by-1571
38 \multiply\count1  by-1\Sin}

Linear transformation of T giving theta := a*T+b, where T = count0*10^(-6);

theta = count1*10^(-3); a = #1*10^3+#2+#3*10^(-3); b = #4*10^(-3)
39 \def\lin#1.#2.#3+#4.{\count1 =#3
40 \count2 =#2 \count3 =#1
41 \multiply\count1 by\count0
42 \multiply\count2 by\count0
43 \multiply\count3 by\count0
44 \divide\count1 by1000
45 \advance\count1 by\count2
46 \divide\count1 by1000
47 \advance\count1 by\count3
48 \advance\count1 by #4}

Accumulate value returned by a trigonometric function, scaled by factor f,

into count6: ac := ac+f*v, where ac = count6*10^(-7) v = value of SIN or
COS =count4*10^(-3) f = #1*10^(-4)
49 \def\fac#1{\multiply\count4  by #1
50 \advance\count6  by\count4}
51 \def\id{\count4=\count1}  % Identity

52 }

53 \ProcessOptions

2.2 First run commands

Create a toggle to flag leap years.

54 ⟨∗style⟩

55 \newif\ifleapyear

Create some counters.

56 \newcounter{date}
57 \newcounter{weekd}
58 \newcounter{Year}
59 \newcounter{yearbase}
60 \newcounter{Month}
61 \newcounter{Day}
62 \newcounter{catch}
63 \newcounter{timezone}

Create a couple of shorthand macros, to keep the interface consistent.

64 \def\theyear{19\the\c@Year}
65 \def\theday{\the\c@Day}

Initialize the time zone to 0.

66 \setcounter{timezone}{0}
\setyear
67 \def\setyear#1{\c@Year=#1
68 \advance\c@Year by-1900\calculateyearbase}
\nextyear
69 \def\nextyear{\advance\c@Year by1
70 \calculateyearbase}
\settimezone
71 \def\settimezone#1{\c@timezone=#1
72 \multiply\c@timezone by 1000
73 \divide\c@timezone by24}

\calculateyearbase Set the \ifleapyear toggle. Set \c@yearbase to the number of days passed from 1900, Jan 0 to New year’s date in the target year.

74 \def\calculateyearbase{%
75 \c@yearbase=-1
76 {\count0=\c@Year\divide\count0 by4
77 \multiply\count0 by4
78 \ifnum\c@Year=\count0
79 \global\c@catch=0\else\global\c@catch=1\fi}%
80 \ifcase\c@catch \leapyeartrue\or
81 \leapyearfalse\fi
82 {\count0=\c@Year\multiply\count0
83 by1461\advance\count0 by3
84 \divide\count0 by4
85 \global\c@catch=\count0}%
86 \advance\c@yearbase by\c@catch
87 \ifnum\c@Year=0\c@yearbase=0\leapyearfalse\fi}

\monthdays Set the number of days passed at the end of each month in \c@Day.

 88 \def\monthdays{\global
 89 \c@catch=\ifcase\c@Month 0\or31\or
 90 59\or90\or120\or151\or181\or212\or
 91 243\or273\or304\or334\or365\fi
 92 {\ifleapyear\ifnum\c@Month>1
 93 \global\advance\c@catch by1\fi\fi}%
 94 \c@Day=\c@catch}
\dayno Return the long date of \c@Month, \c@Day in the year \c@Year in \c@date.
 95 \def\dayno{\c@date=\c@Day{\advance
 96 \c@Month by-1\monthdays
 97 \advance\c@date by\c@Day
 98 \global\advance\c@date by\c@yearbase}}

\weekday Long date MOD 7 gives the week day. Sunday is 0 and Saturday is 6. (This was the documentation to the original file. Not sure what it means.)

 99 \def\weekday{{\count0=\c@date\relax
100 \count1=\count0\divide\count0 by 7
101 \multiply\count0 by 7
102 \advance\count1 by -\count0
103 \global\c@weekd=\count1}}

\theweekday Name of week day (Local).

104 \def\theweekday{\weekday
105 \ifcase\c@weekd
106 Sunday\or Monday\or Tuesday\or
107 Wednesday\or Thursday\or Friday\or
108 Saturday\fi}
\theshortweekday (Local)
109 \def\theshortweekday{\weekday
110 \ifcase\c@weekd Sun\or Mon\or Tue\or
111 Wed\or Thu\or Fri\or Sat\fi}

\caldate Gives the usual calendar date for a long date in counter \c@date. Returned in

 \c@Day, \c@Month and \c@Year
112 \def\caldate{\c@Year=\c@date
113 \multiply\c@Year by4\divide\c@Year by1461
114 \calculateyearbase
115 {\advance\c@date by-\c@yearbase\c@Month=0
116 \loop\monthdays\ifnum\c@Day<\c@date
117 \global\advance\c@Month by1\repeat
118 {\advance\c@Month by-1\monthdays
119 \advance\c@date by-\c@Day
120 \global\c@Day=\c@date}}}

\themonth Name of month \c@Month. (Local)

121 \def\themonth{\ifcase\c@Month
122 \or January\or February\or March\or
123 April\or May\or June\or July\or
124 August\or September\or October\or
125 November\or December\fi}

\nextday Find the next (previous) day after (before) \c@date with \weekday=#1.

126 \def\nextday#1{{\count0=#1\weekday
127 \advance\count0 by-\c@weekd
128 \ifnum\count0<0\advance\count0 by7\fi
129 \global\advance\c@date by\count0}}
\prevday
130 \def\prevday#1{\snextday#1
131 \advance\c@date by-7}
\snextday
132 \def\snextday#1{\advance\c@date by1
133 \nextday#1}
\sprevday
134 \def\sprevday#1{\advance\c@date by-1
135 \prevday#1}
\beginevents \endevents  \beginevents. . . \endevents contains control sequences like \event or \evday or

sequences generating these commands.

136 \newwrite\evefile
137 \def\beginevents{%
138 \immediate\openout
139 \evefile=\jobname.eve\relax}
140 \def\endevents{\immediate\closeout
141 \evefile\end}
\event
142 \newtoks\evetext
143 \def\event#1/#2[#3]{\evetext={#3}%
144 \c@Day=#1\c@Month=#2\dayno
145 \evday[\the\evetext]}
\evday
146 \def\evday[#1]{\immediate\write\evefile{%
147 \string\evententry{\the\c@date}{#1}}}
\thecaldate
148 \def\thecaldate{\the\c@Day/\the\c@Month}
\mute
149 \def\mute{\def\thecaldate{}}

2.3 Second run commands

We need a few counters.

150 \newcount\currentdate
151 \newcount\lastdate
152 \newcount\nextdate

We also need a few toggles.

153 \newif\ifdoing@day
154 \newif\ifholy

\holy
155 \def\holy{\global\holytrue}
\upto
156 \def\upto#1{\nextdate=#1
157 \loop\advance\currentdate by1\relax
158 \ifnum\currentdate<\nextdate
159 \begin@day\end@day\repeat}

\evententry This macro is invoked once for every event exported to the jobname.eve file by the selected date calculation engines contained in the various *.cle files. The invocations occur after \begin@day has been invoked once by \makeagenda. \begin@day sets \ifdoing@day to true, so this toggle is set on when the import takes place. After the import, \end@day is invoked, which turns off \ifdoing@day. \upto then produces empty templates until the current date is hit, and the macro then dumps the message text before calling \end@day. Processing is then passed to the next entry in the jobname.eve file. This method was inherited from the original TEX package. It assumes that the events listed in the jobname.eve file will be in linear order. It therefore does not lend itself to use with multiple event files. To overcome this limitation, we will need to store the event dates in a list macro that can then be sorted before producing the printed output, calling macros named for each event date and the events engine from which it was generated.

160 \def\evententry#1#2{\unskip

If the date established for the event in the current year falls after the last date in the processing range, do nothing at all.

161 \ifnum#1>\lastdate\else

If the date established falls before the earliest date in the range, do nothing at all.

162 \ifnum\currentdate<#1

The following looks like a bug to me, although I could be missing something. It appears that if the very first date in the range is an event date, the event will be skipped. Otherwise, though, we do a single blank entry, then roll forward with blank entries until the current event date given as the first argument to

\evententry is reached.
163 \ifdoing@day\end@day\fi
164 \upto{#1}\fi

When that happens, \currentdate will naturally be a match. The bug referred to above, if it is a bug, might be addressed by eliminating the initializing \begin@day from the \makeagenda macro. It would then be provided by the code below, immediately before the output of the event text.

165 \ifnum\currentdate=#1
166 \ifdoing@day\else\begin@day\fi
167 #2\par\fi\fi}
\begin@day
168 \def\begin@day{\doing@daytrue
169 \c@date=\currentdate\caldate
170 \message{<\thecaldate}\beginday}

\end@day
171 \def\end@day{\endday\doing@dayfalse
172 \global\holyfalse\message{>}}

\makeagenda This is the business end of the TEX macros. If an appropriate style is fed to this macro after invoking \setyear, a calendar will be generated.

173 \def\makeagenda#1{\input #1.sty\relax
174 \begin@day\input\jobname.eve\relax
175 \evententry{\the\lastdate}{}\end@day
176 \epilog\end}

\makeempty Do not read events

177 \def\makeempty{\begin@day
178 \evententry{\the\lastdate}{}\end@day}

\ParseDate Break up a date in the first and second arguments to \everyday into its components in \c@Year, \c@Month and \c@Day, and set the corresponding long date in

 \c@date.
179 \def\ParseDate#1{\@ParseDate#1\end}
180 \def\@ParseDate#1/#2/#3\end{\setyear{#1}\c@Month=#2\c@Day=#3\dayno}

\everyday Set \currentdate and \lastdate to set the boundaries of iteration and define the bracketing macros \beginday and \endday. Initiate iteration by invoking

 \makeempty.
181 \def\everyday#1#2#3{\ParseDate{#1}\currentdate=\c@date%
182 \ParseDate{#2}\lastdate=\c@date%
183 \def\beginday{#3}%
184 \def\endday{}\makeempty}

185 ⟨/style⟩

3 The Installation File

186 ⟨∗installer⟩

187 \def\batchfile{calendar.ins}
188 \input docstrip.tex

189

190 \keepsilent

191

192 \preamble

193

194 This file is part of the Calendar package.
195 Copyright (C) 1996 Frank Bennett, Jr.
196 All rights reserved.
197 ------------------------------------------
198 This is a generated file.

199

200 IMPORTANT NOTICE:

201

202 You are not allowed to change this file.  You may however copy
203 this file to a file with a different name and then change the
204 copy if (a) you do not charge for the modified code, (b) you
205 acknowledge the author(s) in the new file, if it

206 is distributed to others, and (c) you attach these same
207 conditions to the new file.

208

209 You are not allowed to distribute this file alone.  You are not
210 allowed to take money for the distribution or use of this file
211 (or a changed version) except for a nominal charge for copying
212 etc.

213

214 You are allowed to distribute this file under the condition that
215 it is distributed with all of its contents, intact.

216

217 For error reports, or offers to help make Calendar a more powerful,
218 friendlier, and better package, please contact me on
219 `fb' at soas.ac.uk

220

221 \endpreamble

222

223 \generateFile{calendar.sty}   {t}{\from{calendar.dtx}{style}}

224

225 \Msg{***********************************************************}
226 \Msg{*}
227 \Msg{* To finish the installation, you have to move the following}
228 \Msg{* file into a directory searched by TeX:}
229 \Msg{*}
230 \Msg{* \space\space calendar.sty}
231 \Msg{*}
232 \Msg{***********************************************************}

233 } 234 ⟨/installer⟩