--
require('strict')
local p = local cfg -- Data structure from ~/eventslocal eventdata -- Data structure from ~/localfiles/
----------------------------< inlineError >-----------------------
Critical error. Render output completely in red. Add to tracking category.
local function inlineError(arg, msg, tname)
track["Category:Calendar date template errors"] = 1 return '
Error in - Check|' .. arg .. '=
' .. msg .. ''end
----------------------------< trimArg >-----------------------
trimArg returns nil if arg is "" while trimArg2 returns 'true' if arg is "" trimArg2 is for args that might accept an empty value, as an on/off switch like nolink=
local function trimArg(arg) if arg
nil then return nil else return mw.text.trim(arg) endendlocal function trimArg2(arg) if arg
----------------------------< tableLength >-----------------------
Given a 1-D table, return number of elements
local function tableLength(T) local count = 0 for _ in pairs(T) do count = count + 1 end return countend
--D] ]; if only link is provided, returns a wikilink in the form [[L] ]; if neither are provided or link is omitted, returns an empty string.
local function make_wikilink (link, display, no_link) if nil
----------------------------< createTracking >-----------------------
Return data in track[] ie. tracking categories
local function createTracking
local out = ; if tableLength(track) > 0 then for key, _ in pairs(track) do -- loop through table table.insert (out, make_wikilink (key)) -- and convert category names to links end end return table.concat (out) -- concat into one big string; empty string if table is emptyend
----------------------------< isValidDate >----------------------------------------------------
Returns true if date is after 31 December 1899, not after 2100, and represents a valid date (29 February 2017 is not a valid date). Applies Gregorian leapyear rules. All arguments are required.
local function isValidDate (year, month, day)
local days_in_month = local month_length local y, m, d local today = os.date ('*') -- fetch a table of current date parts
if not year or year
or not day or day
y = tonumber (year) m = tonumber (month) d = tonumber (day)
if 1900 > y or 2100 < y or 1 > m or 12 < m then -- year and month are within bounds return false end
if (2
(y%4) and (0~=(y%100) or 0
if 1 > d or month_length < d then -- day is within bounds return false end return trueend
----------------------------< makeDate >-----------------------
Given a zero-padded 4-digit year, 2-digit month and 2-digit day, return a full date in df format df = mdy, dmy, iso, ymd
local function makeDate(year, month, day, df, format) local formatFull = local formatInfobox =
if not year or year
"" or not day or day
local date = table.concat -- assemble iso format date if format ~= "infobox" then return mw.getContentLanguage:formatDate (formatFull[df], date) else return mw.getContentLanguage:formatDate (formatInfobox[df], date) endend
----------------------------< dateOffset >-----------------------
Given a 'origdate' in ISO format, return the date offset by number of days in 'offset' eg. given "2018-02-01" and "-1" it will return "2018-01-30" On error, return origdate
local function dateOffset(origdate, offset)
local year, month, day = origdate:match ('(%d%d%d%d)-(%d%d)-(%d%d)') local now = os.time local newdate = os.date("%Y-%m-%d", now + (tonumber(offset) * 24 * 3600)) return newdate and newdate or origdate
end
----------------------------< renderHoli >-----------------------
Render the data
local function renderHoli(cfg,eventdata,calcdate,date,df,format,tname,cite)local hits = 0 local matchdate = "^" .. date local startdate,enddate,outoffset,endoutoffset = nil local starttitle,endtitle = ""
-- user-supplied date calculator if cfg.datatype
-- read dates from localfile -- it assumes dates are in chrono order, need a more flexible method elseif cfg.datatype
0 then startdate = eventdata[i].date hits = 1 end if hits >= tonumber(cfg.days) then enddate = eventdata[i].date break end hits = hits + 1 end end end -- Verify data and special conditions if startdate
nil then if cfg.name
"localfile" and cfg.days > "1" and startdate then enddate = dateOffset(startdate, cfg.days - 1) elseif startdate and not enddate then return inlineError("year", 'cannot find enddate', tname) .. createTracking else return inlineError("holiday", 'cannot find startdate and enddate', tname) .. createTracking end end -- Generate start-date offset (ie. holiday starts the evening before the given date) if cfg.startoffset then startdate = dateOffset(startdate, cfg.startoffset) if startdate ~= enddate then enddate = dateOffset(enddate, cfg.startoffset) else cfg.days = (cfg.days
-- Format dates into df format local year, month, day = startdate:match ('(%d%d%d%d)-(%d%d)-(%d%d)') startdate = makeDate(year, month, day, df, format) year, month, day = enddate:match ('(%d%d%d%d)-(%d%d)-(%d%d)') enddate = makeDate(year, month, day, df, format) if startdate
nil then return nil end
-- Add "outside of Israel" notices if endoutoffset then year, month, day = endoutoffset:match ('(%d%d%d%d)-(%d%d)-(%d%d)') local leader = ((format
--- Determine format string format = ((format
--- Determine pre-pended text string eg. "sunset,
-- return output if startdate
"1" then -- single date return prepend1 .. startdate .. endoutoffset .. cite else return prepend1 .. startdate .. format .. prepend2 .. enddate .. endoutoffset .. cite endend
----------------------------< calendardate >-----------------------
Main function
function p.calendardate(frame)
local pframe = frame:getParent local args = pframe.args
local tname = "Calendar date" -- name of calling template. Change if template rename. local holiday = nil -- name of holiday local date = nil -- date of holiday (year) local df = nil -- date format (mdy, dmy, iso - default: iso) local format = nil -- template display format options local cite = nil -- leave a citation at end local calcdate = ""
--- Determine holiday holiday = trimArg(args.holiday) -- required if not holiday then holiday = trimArg(args.event) -- event alias if not holiday then return inlineError("holiday", 'missing holiday argument', tname) .. createTracking end end
--- Determine date date = trimArg(args.year) -- required if not date then return inlineError("year", 'missing year argument', tname) .. createTracking elseif not isValidDate(date, "01", "01") then return inlineError("year", 'invalid year', tname) .. createTracking end
--- Determine format type format = trimArg(args.format) if not format then format = "none" elseif format ~= "infobox" then format = "none" end
-- Load configuration file local eventsfile = mw.loadData ('Module:Calendar date/events') if eventsfile.hebrew_calendar[mw.ustring.upper(holiday)] then cfg = eventsfile.hebrew_calendar[mw.ustring.upper(holiday)] elseif eventsfile.christian_events[mw.ustring.upper(holiday)] then cfg = eventsfile.christian_events[mw.ustring.upper(holiday)] elseif eventsfile.carnivals[mw.ustring.upper(holiday)] then cfg = eventsfile.carnivals[mw.ustring.upper(holiday)] elseif eventsfile.chinese_events[mw.ustring.upper(holiday)] then cfg = eventsfile.chinese_events[mw.ustring.upper(holiday)] elseif eventsfile.misc_events[mw.ustring.upper(holiday)] then cfg = eventsfile.misc_events[mw.ustring.upper(holiday)] else return inlineError("holiday", 'unknown holiday ' .. holiday, tname) .. createTracking end
-- If datatype = localfile if cfg.datatype
-- If datatype = calculator elseif cfg.datatype
--- Determine df - priority to |df in template, otherwise df in datafile, otherwise default to dmy df = trimArg(args.df) if not df then df = (cfg.df and cfg.df) or "dmy" end if df ~= "mdy" and df ~= "dmy" and df ~= "iso" then df = "dmy" end
-- Determine citation cite = trimArg2(args.cite) if cite then if (cite ~= "no") then cite = "" if cfg.citeurl and cfg.accessdate and cfg.source and cfg.name then local citetitle = cfg.citetitle if citetitle
-- Render local rend = renderHoli(cfg,eventdata,calcdate,date,df,format,tname,cite) if not rend then rend = '
Error in : Unknown problem. Please report on template talk page.' track["Category:Webarchive template errors"] = 1 endreturn rend .. createTracking
end
return p