\NeedsTeXFormat{LaTeX2e} \ProvidesPackage{easter}[2026/07/07 Implementation of the Meeus algorithms to compute Easter's date an related feasts according to Gregorian and Julian computus.] %Algorithms source: https://fr.wikipedia.org/wiki/Calcul_de_la_date_de_P%C3%A2ques_selon_la_m%C3%A9thode_de_Meeus \newif\ife@printdate\e@printdatetrue \def\e@error#1{\typeout{^^J\space\space** Package easter error: #1 **^^J}} \def\Easter{\e@error{please select a computus^^J\space\space before computing Easter-related dates.}} \RequirePackage{datenumber} \let\oldssy\setstartyear \def\setstartyear#1{% \ifnum#1>\the\year \oldssy{\the\year}% \else \oldssy{#1}\fi} %Defining Easter date counters \newcounter{EasterYear} \newcounter{EasterMonth} \newcounter{EasterDay} \newcounter{AscensionYear} \newcounter{AscensionMonth} \newcounter{AscensionDay} \newcounter{PentecostYear} \newcounter{PentecostMonth} \newcounter{PentecostDay} \newcounter{TransposedYear} \newcounter{TransposedMonth} \newcounter{TransposedDay} \def\printDate#1{\csname the#1Year\endcsname% -\expandafter\two@digits\csname the#1Month\endcsname% -\expandafter\two@digits\csname the#1Day\endcsname} %Compute the Euclidian division of #1 by #2, %returning both the quotient (#3) and the remainder (#4). %#3 and #4 are TeX counters. %#1: dividend (input), #2: divisor (input), #3: quotient (output), #4: remainder (output) \newcount\dividend \newcount\divisor \def\EuclidianDiv#1#2#3#4{% \dividend\numexpr#1\relax% \divisor\numexpr#2\relax% % \newcount#3#3\dividend% \divide#3 by\divisor% \newcount#4#4\numexpr\dividend-\divisor*#3\relax} %Butcher-Meeus algorithm \def\EasterGregorian{% \begingroup\@ifstar% {\global\e@printdatefalse\@EasterGregorian}% {\global\e@printdatetrue\@EasterGregorian}} \newcommand{\@EasterGregorian}[1][\year]{% \ifnum#1<1583 \e@error{invalid year #1 for Gregorian comput^^J\space\space(must be >=1583).} \else \setcounter{EasterYear}{\numexpr#1}% % \EuclidianDiv{\theEasterYear}{19}{\void}{\n}% \EuclidianDiv{\theEasterYear}{100}{\c}{\u}% \EuclidianDiv{\c}{4}{\s}{\t}% \EuclidianDiv{\c+8}{25}{\p}{\void}% \EuclidianDiv{\c-\p+1}{3}{\q}{\void}% \EuclidianDiv{19*\n+\c-\s-\q+15}{30}{\void}{\e}% \EuclidianDiv{\u}{4}{\b}{\d}% \EuclidianDiv{2*\t+2*\b-\e-\d+32}{7}{\void}{\L}% \EuclidianDiv{\n+11*\e+22*\L}{451}{\h}{\void}% \EuclidianDiv{\e+\L-7*\h+114}{31}{\m}{\j}% % \setcounter{EasterMonth}{\m}% \setcounter{EasterDay}{\numexpr\j+1}% \ife@printdate \printDate{Easter}\fi \fi\endgroup} %Delambre-Meeus algorithm \def\EasterJulian{% \begingroup\@ifstar {\global\e@printdatefalse\@EasterJulian}% {\global\e@printdatetrue\@EasterJulian}} \newcommand{\@EasterJulian}[1][\year]{% \ifnum#1<326 \e@error{invalid year #1 for Julian comput^^J\space\space(must be >=326).} \else \setcounter{EasterYear}{\numexpr#1}% % \EuclidianDiv{\theEasterYear}{19}{\void}{\A}% \EuclidianDiv{\theEasterYear}{7}{\void}{\B}% \EuclidianDiv{\theEasterYear}{4}{\void}{\C}% \EuclidianDiv{19*\A+15}{30}{\void}{\D}% \EuclidianDiv{2*\C+4*\B-\D+34}{7}{\void}{\E}% \EuclidianDiv{\D+\E+114}{31}{\F}{\G}% % \setcounter{EasterMonth}{\F}% \setcounter{EasterDay}{\numexpr\G+1}% \ife@printdate \printDate{Easter}\fi \fi\endgroup} %Computes the date of Ascension and Pentecost after Easter's date \def\Ascension{% \begingroup\@ifstar {\global\e@printdatefalse\@Ascension}% {\global\e@printdatetrue\@Ascension}} \newcommand{\@Ascension}[1][\year]{% \setcounter{AscensionYear}{\numexpr#1}% % \let\oldife@printdate\ife@printdate \ifnum\theEasterYear=0 \Easter*[#1] \else\ifnum#1=\theEasterYear\else \Easter*[#1]\fi\fi \let\ife@printdate\oldife@printdate % \setstartyear{\theAscensionYear}% \setdatenumber{\theEasterYear}{\theEasterMonth}{\theEasterDay}% \addtocounter{datenumber}{39}% \setmydatebynumber{\thedatenumber}{AscensionYear}{AscensionMonth}{AscensionDay}% % \ife@printdate \printDate{Ascension}\fi\endgroup} \def\Pentecost{% \begingroup\@ifstar {\global\e@printdatefalse\@Pentecost}% {\global\e@printdatetrue\@Pentecost}} \newcommand{\@Pentecost}[1][\year]{% \setcounter{PentecostYear}{\numexpr#1}% % \let\oldife@printdate\ife@printdate \ifnum\theEasterYear=0 \Easter*[#1] \else\ifnum#1=\theEasterYear\else \Easter*[#1]\fi\fi \let\ife@printdate\oldife@printdate % \setstartyear{\thePentecostYear}% \setdatenumber{\theEasterYear}{\theEasterMonth}{\theEasterDay}% \addtocounter{datenumber}{49}% \setmydatebynumber{\thedatenumber}{PentecostYear}{PentecostMonth}{PentecostDay}% % \ife@printdate \printDate{Pentecost}\fi\endgroup} %Computes de offset between calendars such that Julian + offset = Gregorian %Offset for a single year is valid starting the day following February the 28th in both calendars. \newcounter{calendaroffset} \newcount\@tempA \newcount\@tempB \def\calendarOffset{\begingroup\@calendarOffset} \newcommand{\@calendarOffset}[1][\year]{% \@tempA\numexpr#1\relax% \@tempB\@tempA % \divide\@tempA by 100% \divide\@tempB by 400% % \setcounter{calendaroffset}{\numexpr\@tempA-\@tempB-2}% \endgroup} %Transpose dates from a calendar to the other. %#1: year, #2: month, #3: day \newcount\offsetYear \def\toGregorian#1#2#3{% \offsetYear\numexpr#1\relax \ifnum#2<2 \advance\offsetYear by -1\relax% \else\ifnum#2=2\ifnum#3>28\else \advance\offsetYear by -1\relax% \fi\fi\fi % \setstartyear{#1}% \setdatenumber{#1}{#2}{#3}% \calendarOffset[\offsetYear]% \addtocounter{datenumber}{\thecalendaroffset}% \setmydatebynumber{\thedatenumber}{TransposedYear}{TransposedMonth}{TransposedDay}} \def\toJulian#1#2#3{% \offsetYear\numexpr#1\relax \ifnum#2<2 \advance\offsetYear by -1\relax% \else\ifnum#2=2\ifnum#3>28\else \advance\offsetYear by -1\relax% \fi\fi\fi % \setstartyear{#1}% \setdatenumber{#1}{#2}{#3}% \calendarOffset[\offsetYear]% \addtocounter{datenumber}{-\thecalendaroffset}% \setmydatebynumber{\thedatenumber}{TransposedYear}{TransposedMonth}{TransposedDay}} %Option processing: computus selection \def\@gregorian{gregorian} \def\@julian{julian} \def\selectComputus#1{% \def\@computus{#1} \ifx\@computus\@gregorian \let\Easter\EasterGregorian \else\ifx\@computus\@julian \let\Easter\EasterJulian \fi\fi} \DeclareOption{gregorian}{\selectComputus{gregorian}} \DeclareOption{julian}{\selectComputus{julian}} \ProcessOptions\relax