Module:Easter
MyWikiBiz, Author Your Legacy — Thursday November 14, 2024
Jump to navigationJump to searchModule to calculate Easter dates and dates relative to Easter.
Calculate
Function to calculate Easter date or date of the event related to Easter.
arguments
Field | Purpose | Example argument |
---|---|---|
1 | Year | 2024 or 1882
|
method | Calculation method of the Easter date:
|
Eastern to calculate Easter date in the Orthodox rite.
|
day | Name of the event related to Easter date or integer number of days before (negative) or after (positive) Easter Sunday. The following days are available by name:
|
49 or interchangeably Pentecost
|
format | Describes date format in the final output, which is the same as used in #time parser function. Default format is Y-m-d . There is a special value none that prevents from final date formatting.
|
j xd
|
examples
{{#invoke:Easter|Calculate|{{CURRENTYEAR}}}}
- 2024-03-31
{{#invoke:Easter|Calculate|{{CURRENTYEAR}}|method=Eastern}}
- 2024-05-05
{{#invoke:Easter|Calculate|{{CURRENTYEAR}}|format=[[j xg]]}}
- 31 March
{{#invoke:Easter|Calculate|{{CURRENTYEAR}}|method=Eastern|format=[[j xg]]}}
- 5 May
{{#invoke:Easter|Calculate|{{CURRENTYEAR}}|day=Ash Wednesday}}
- 2024-02-14
{{#invoke:Easter|Calculate|{{CURRENTYEAR}}|method=Eastern|day=Ash Wednesday}}
- 2024-03-20
{{#invoke:Easter|Calculate|{{CURRENTYEAR}}|format=[[j xg]] (l)|day=Ash Wednesday}}
- 14 February (Wednesday)
{{#invoke:Easter|Calculate|{{CURRENTYEAR}}|method=Eastern|format=[[j xg]] (l)|day=Ash Wednesday}}
- 20 March (Wednesday)
local m = {} local EasterData = { defaultMethod = 3, -- default method of Easter date calculation when Easter type is not given defaultFormat = "Y-m-d", -- default date output format noFormat = "none", -- prevent from final date formatting defaultOffset = 0, -- the Easter date minimumOffset = -63, -- Septuagesima maximumOffset = 69, -- Feast of the Immaculate Heart of Mary -- API apiEaster = "Calculate", -- public function name argEasterYear = 1, -- index or name of the argument with year argEasterMethod = "method", -- index or name of the argument with calculation method argEasterOffset = "day", -- index or name of the argument with offset in days relative to the calculated Easter Sunday argEasterFormat = "format", -- index or name of the argument with date output format (#time style) -- errors errorMissingYear = "Missing mandatory argument 'year'", errorInvalidYear = "Incorrect argument 'year': '%s'", errorInvalidOffset = "Incorrect argument 'day': '%s'", errorInvalidMethod = "Incorrect argument 'method': '%s'", errorYearOutOfRange = "Easter dates are available between years 326 and 4099; year: %d", errorIncorrectMethod = "Western or Orthodox Easter exists since 1583; year: %d", errorUnknownMethod = "Unknown method: %d", methods = { ["Julian"] = 1, ["Eastern"] = 2, ["Orthodox"] = 2, -- alias for Eastern ["Coptic"] = 2, -- alias for Eastern ["Ethiopian"] = 2, -- alias for Eastern ["Western"] = 3, ["Gregorian"] = 3, -- alias for Western ["Roman"] = 3, -- alias for Western }, -- the Meletian/Revised Julian Calendar from 1923 used by some Orthodox churches -- and any proposed reformed algorithms are not supported (yet): -- * astronomically observed Nicean rule at the meridian of Jerusalem (Aleppo 1997 proposal), differs from Gregorian in -- * fifteenth Sunday of the year: Sunday in 099–105 day of the year -- * Sunday after second Saturday in April (UK): Sunday in 9–15 April -- * second Sunday in April: Sunday in 8–14 April -- * Sunday after 6 April (Pepuzite sect): Sunday in 7–13 April -- * World Calendar: day 099, any day of the week in Gregorian/Julian calendar -- * Positivist Calendar: day 098, any day of the week in Gregorian/Julian calendar -- * Sunday of ISO week 14: Sunday in 099–105 day of the year -- * Sunday of ISO week 15: Sunday in 106–112 day of the year -- * Nisan 14: any day of the week -- * Nisan 15: any day of the week relativeDates = { ["Septuagesima"] = -63, ["Sexagesima"] = -56, ["Fat Thursday"] = -52, ["Quinquagesima"] = -49, -- Estomihi, Shrove Sunday ["Shrove Monday"] = -48, -- Rose Monday ["Shrove Tuesday"] = -47, -- Mardi Gras, Carnival ["Ash Wednesday"] = -46, ["Invocabit Sunday"] = -42, ["Reminiscere Sunday"] = -35, ["Oculi Sunday"] = -28, ["Laetare Sunday"] = -21, -- Mothering Sunday ["Holy Week"] = -7, ["Palm Sunday"] = -7, ["Holy Monday"] = -6, ["Holy Tuesday"] = -5, ["Holy Wednesday"] = -4, ["Maundy Thursday"] = -3, ["Good Friday"] = -2, -- Crucifixion ["Holy Saturday"] = -1, ["Easter"] = 0, -- Easter Sunday, Resurrection ["Easter Monday"] = 1, ["Divine Mercy"] = 7, ["Misericordias Domini"] = 14, ["Jubilate Sunday"] = 21, ["Cantate Sunday"] = 28, ["Vocem jucunditatis"] = 35, ["Ascension Thursday"] = 39, -- Ascension ["Pentecost"] = 49, -- Whitsun ["Whit Monday"] = 50, ["Trinity Sunday"] = 56, ["Corpus Christi"] = 60, -- Body and Blood of Christ ["Sacred Heart"] = 68, ["Immaculate Heart"] = 69, }, } local function formatEasterError(message, ...) if select('#', ... ) > 0 then message = string.format(message, ...) end return "<span class=\"error\">" .. message .. "</span>" end local function loadEasterYear(year) if not year then return false, formatEasterError(EasterData.errorMissingYear) end local result = tonumber(year) if not result or math.floor(result) ~= result then return false, formatEasterError(EasterData.errorInvalidYear, year) end return true, result end local function loadEasterMethod(method, year) local result = EasterData.defaultMethod if method then result = EasterData.methods[method] if not result then return false, formatEasterError(EasterData.errorInvalidMethod, method) end end if year < 1583 then result = 1 end return true, result end local function loadEasterOffset(day) if not day then return true, "" end local data = EasterData.relativeDates local offset = tonumber(day) if not offset then offset = data[day] end if not offset or offset ~= math.floor(offset) or offset < EasterData.minimumOffset or offset > EasterData.maximumOffset then return false, formatEasterError(EasterData.errorInvalidOffset, day) end if offset < -1 then return true, string.format(" %d days", offset) elseif offset == -1 then return true, " -1 day" elseif offset == 0 then return true, "" elseif offset == 1 then return true, " +1 day" else -- if offset > 1 then return true, string.format(" +%d days", offset) end end local function loadEasterFormat(fmt) if fmt == EasterData.noFormat then return true, nil elseif not fmt then return true, EasterData.defaultFormat else return true, fmt end end --[[ PURPOSE: This function returns Easter Sunday day and month for a specified year and method. INPUTS: Year - Any year between 326 and 4099. Method - 1 = the original calculation based on the Julian calendar 2 = the original calculation, with the Julian date converted to the equivalent Gregorian calendar 3 = the revised calculation based on the Gregorian calendar OUTPUTS: None. RETURNS: 0, error message - Error; invalid arguments month, day - month and day of the Sunday NOTES: The code is translated from DN OSP 6.4.0 sources. The roots of the code might be found in http://www.gmarts.org/index.php?go=415 ORIGINAL NOTES: This algorithm is an arithmetic interpretation of the 3 step Easter Dating Method developed by Ron Mallen 1985, as a vast improvement on the method described in the Common Prayer Book Published Australian Almanac 1988 Refer to this publication, or the Canberra Library for a clear understanding of the method used Because this algorithm is a direct translation of the official tables, it can be easily proved to be 100% correct It's free! Please do not modify code or comments! ]] local function calculateEasterDate(year, method) if year < 326 or year > 4099 then -- Easter dates are valid for years between 326 and 4099 -- Method 2 would have to support dates in June thereafter return 0, formatEasterError(EasterData.errorYearOutOfRange, year) end if year < 1583 and method ~= 1 then -- Western or Orthodox Easter is valid since 1583 return 0, formatEasterError(EasterData.errorIncorrectMethod, year) end -- intermediate result local firstDig = math.floor(year / 100) local remain19 = year % 19 local temp = 0 -- table A to E results local tA = 0 local tB = 0 local tC = 0 local tD = 0 local tE = 0 -- Easter Sunday day local d = 0 if method == 1 or method == 2 then -- calculate PFM date tA = ((225 - 11 * remain19) % 30) + 21 -- find the next Sunday tB = (tA - 19) % 7 tC = (40 - firstDig) % 7 temp = year % 100 tD = (temp + math.floor(temp / 4)) % 7 tE = ((20 - tB - tC - tD) % 7) + 1 d = tA + tE if method == 2 then -- convert Julian to Gregorian date -- 10 days were skipped in the Gregorian calendar from 5-14 Oct 1582 temp = 10 -- only 1 in every 4 century years are leap years in the Gregorian -- calendar (every century is a leap year in the Julian calendar) if year > 1600 then temp = temp + firstDig - 16 - math.floor((firstDig - 16) / 4) end d = d + temp end elseif method == 3 then -- calculate PFM date temp = math.floor((firstDig - 15) / 2) + 202 - 11 * remain19 if firstDig > 26 then temp = temp - 1 end if firstDig > 38 then temp = temp - 1 end if firstDig == 21 or firstDig == 24 or firstDig == 25 or firstDig == 33 or firstDig == 36 or firstDig == 37 then temp = temp - 1 end temp = temp % 30 tA = temp + 21 if temp == 29 then tA = tA - 1 end if temp == 28 and remain19 > 10 then tA = tA - 1 end -- find the next Sunday tB = (tA - 19) % 7 tC = (40 - firstDig) % 4 if tC == 3 then tC = tC + 1 end if tC > 1 then tC = tC + 1 end temp = year % 100 tD = (temp + math.floor(temp / 4)) % 7 tE = ((20 - tB - tC - tD) % 7) + 1 d = tA + tE else -- Unknown method return 0, formatEasterError(EasterData.errorUnknownMethod, method) end if d > 61 then -- when the original calculation is converted to the Gregorian -- calendar, Easter Sunday can occur in May return 5, d - 61 elseif d > 31 then return 4, d - 31 else return 3, d end end local function Easter(args) local ok local year ok, year = loadEasterYear(args[EasterData.argEasterYear]) if not ok then return year end local method ok, method = loadEasterMethod(args[EasterData.argEasterMethod], year) if not ok then return method end local offset ok, offset = loadEasterOffset(args[EasterData.argEasterOffset]) if not ok then return offset end local format ok, format = loadEasterFormat(args[EasterData.argEasterFormat]) if not ok then return format end local month, day = calculateEasterDate(year, method) if month == 0 then return day end local result = string.format("%04d-%02d-%02d%s", year, month, day, offset) if format then result = mw.language.getContentLanguage():formatDate(format, result) end return result end m[EasterData.apiEaster] = function (frame) return Easter(frame.args) end return m