Module:Calendar date/recurring

--[[

Calculates the Gregorian date of a recurring holiday that varies year-to-year, but follows the rule "Nth [day of week] of [month]"

"month" = month number (1 to 12) "weeknumber" = number of week (1 to 4, or -1 to mean "last") "dayofweek" = number that represents the day of the week, where 1 = Sunday and 7 = Saturday "year" = Gregorian calendar year ]]

require('strict')

local p = {}

function p.calculate(frame) local args = frame.args

local ONE_DAY = 86400 -- number of seconds in one day local year = tonumber(args.year) local month = tonumber(args.month) local weeknumber = tonumber(args.weeknumber) local dayofweek = tonumber(args.dayofweek)

local date = os.time{year=year, month=month, day=1} local dateparts = os.date("*t", date) if weeknumber > 0 then -- find the first [dayofweek] of this month while dateparts["wday"] ~= dayofweek do			date = date + ONE_DAY dateparts = os.date("*t", date) end

-- add the correct number of weeks if weeknumber > 1 then date = date + ((weeknumber - 1) * (7 * ONE_DAY)) end else -- find the first day of the next month while dateparts["month"] == month do			date = date + ONE_DAY dateparts = os.date("*t", date) end

-- go back one day to get the last day of the month we want date = date - ONE_DAY dateparts = os.date("*t", date)

-- go backwards until we find the right day of week while dateparts["wday"] ~= dayofweek do			date = date - ONE_DAY dateparts = os.date("*t", date) end end local result = os.date("%Y-%m-%d", date) return result

end

return p