[How-To] Calculate the date of Easter Sunday, for both the Gregorian and the Julian (Orthodox) Calendar
Posted: 29 Sep 2020 11:18
Because of a recent request I searched the forum for an Easter calculation but didn't find one. Here you go ...
Gregorian Calendar
The Easter calculation is based on the Anonymous Easter Algorithm for the Gregorian calendar.
https://en.wikipedia.org/wiki/Computus# ... _algorithm
It's shortened by replacing some variables with their formula.
The algorithm has been verified using the years with an Easter-paradox in the code above. Those are years where the astronomically correct Easter date is other than the Easter date calculated by the agreed algorithm for the Gregorian calendar. The output has to be always the latter.
https://en.wikipedia.org/wiki/Computus# ... ster_dates
https://de.wikipedia.org/wiki/Osterparadoxon (German site because I didn't find an appropriate English one.)
The :easter subroutine expects a four digits year as parameter. It returns the date of Easter Sunday using format YYYYMMDD, accessible in the errorlevel variable. The format meets the order of the first 8 digits of the WMI LocalDateTime string to facilitate comparisons.
Julian Calendar
In a couple of counties the calculation is based on the Julian Calendar, e.g. the Russian-Orthodox Easter (Пасха). This is both easier and more difficult at the same time. The actual calculation is shorter. I used Meeus's Julian algorithm.
https://en.wikipedia.org/wiki/Computus# ... _algorithm
The result is Easter in the Julian calendar. This is likely not quite helpful though. Even if the Julian calendar is used to determine the date, the official calendar in those countries will be probably the Gregorian calendar. Thus, it might be required to convert from the Julian to the Gregorian calendar date afterwards.
Parameter format for :easter_jul is YYYY, the returned value has format YYYYMMDD.
For :jul2greg both the input parameter and the return value have format YYYYMMDD.
Of course both the Julian Easter calculation and the conversion into a Gregorian date can also be done in one step
Steffen
Gregorian Calendar
Code: Select all
@echo off &setlocal EnableDelayedExpansion
for %%i in (1590 1666 1685 1924 1943 1962 2019 2038 2057 2076 2095 2133 2152 2171 2190) do (
call :easter %%i
echo !errorlevel!
)
echo ~~~~~~~~~~~~~~~
for %%i in (1876 1974 2045 2069 2089 2096) do (
call :easter %%i
echo !errorlevel!
)
echo ~~~~~~~~~~~~~~~
for %%i in (1802 1805 1818 1825 1829 1845 1900 1903 1923 1927 1954 1967 1981 2049 2076 2106 2119 2133 2147 2150 2170 2174) do (
call :easter %%i
echo !errorlevel!
)
pause
goto :eof
:easter
setlocal
set /a "y=%~1,a=y%%19,b=y/100,c=y%%100,h=(19*a+b-b/4-(b-(b+8)/25+1)/3+15)%%30,l=(32+b%%4*2+c/4*2-h-c%%4)%%7,n=h+l-(a+11*h+22*l)/451*7+114,o=y*10000+n/31*100+n%%31+1"
endlocal &exit /b %o%
https://en.wikipedia.org/wiki/Computus# ... _algorithm
It's shortened by replacing some variables with their formula.
The algorithm has been verified using the years with an Easter-paradox in the code above. Those are years where the astronomically correct Easter date is other than the Easter date calculated by the agreed algorithm for the Gregorian calendar. The output has to be always the latter.
https://en.wikipedia.org/wiki/Computus# ... ster_dates
https://de.wikipedia.org/wiki/Osterparadoxon (German site because I didn't find an appropriate English one.)
The :easter subroutine expects a four digits year as parameter. It returns the date of Easter Sunday using format YYYYMMDD, accessible in the errorlevel variable. The format meets the order of the first 8 digits of the WMI LocalDateTime string to facilitate comparisons.
Code: Select all
@echo off &setlocal
for /f %%i in ('WMIC OS Get LocalDateTime /value') do for /f %%j in ("%%i") do set "%%j"
call :easter %LocalDateTime:~0,4%
if %errorlevel%==%LocalDateTime:~0,8% echo Happy Easter!
pause
goto :eof
:easter
setlocal
set /a "y=%~1,a=y%%19,b=y/100,c=y%%100,h=(19*a+b-b/4-(b-(b+8)/25+1)/3+15)%%30,l=(32+b%%4*2+c/4*2-h-c%%4)%%7,n=h+l-(a+11*h+22*l)/451*7+114,o=y*10000+n/31*100+n%%31+1"
endlocal &exit /b %o%
Julian Calendar
In a couple of counties the calculation is based on the Julian Calendar, e.g. the Russian-Orthodox Easter (Пасха). This is both easier and more difficult at the same time. The actual calculation is shorter. I used Meeus's Julian algorithm.
https://en.wikipedia.org/wiki/Computus# ... _algorithm
The result is Easter in the Julian calendar. This is likely not quite helpful though. Even if the Julian calendar is used to determine the date, the official calendar in those countries will be probably the Gregorian calendar. Thus, it might be required to convert from the Julian to the Gregorian calendar date afterwards.
Code: Select all
@echo off &setlocal
for /f %%i in ('WMIC OS Get LocalDateTime /value') do for /f %%j in ("%%i") do set "%%j"
call :easter_jul %LocalDateTime:~0,4%
echo Jul.: %errorlevel%
call :jul2greg %errorlevel%
echo Greg.: %errorlevel%
pause
goto :eof
:easter_jul
setlocal
set /a "y=%~1,d=(y%%19*19+15)%%30,f=d+(y%%4*2+y%%7*4-d+34)%%7+114,g=y*10000+f/31*100+f%%31+1"
endlocal &exit /b %g%
:jul2greg
setlocal
set "s=%~1"
set /a "y=%s:~0,4%,m=100%s:~4,2%%%100,d=100%s:~6,2%%%100,a=(14-m)/12,h=(y-a)/100,b=y+4800-a,c=(153*(m+12*a-3)+2)/5+d+b*365+b/4-b/100+b/400+h/4*3+h%%4-3,d=(4*c+3)/146097,e=-d*146097/4+c,f=(4*e+3)/1461,g=(-1461*f)/4+e,h=(5*g+2)/153,i=10000*(d*100+f-4800+h/10)+100*((-h/10)*12+h+3)+((153*h+2)/-5)+g+1"
endlocal &exit /b %i%
For :jul2greg both the input parameter and the return value have format YYYYMMDD.
Of course both the Julian Easter calculation and the conversion into a Gregorian date can also be done in one step
Code: Select all
@echo off &setlocal EnableDelayedExpansion
for %%i in (2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024) do (
call :easter_jul_in_greg %%i
echo !errorlevel!
)
pause
goto :eof
:easter_jul_in_greg
setlocal
set /a "y=%~1,d=(y%%19*19+15)%%30,f=d+(y%%4*2+y%%7*4-d+34)%%7+114,m=f/31,a=(14-m)/12,h=(y-a)/100,b=y+4800-a,c=(153*(m+12*a-3)+2)/5+f%%31+b*365+b/4-b/100+b/400+h/4*3+h%%4-2,d=(4*c+3)/146097,e=-d*146097/4+c,f=(4*e+3)/1461,g=(-1461*f)/4+e,h=(5*g+2)/153,i=10000*(d*100+f-4800+h/10)+100*((-h/10)*12+h+3)+((153*h+2)/-5)+g+1"
endlocal &exit /b %i%