Content deleted Content added
No edit summary |
use require('strict') instead of require('Module:No globals') |
||
(117 intermediate revisions by 4 users not shown) | |||
Line 1:
--[[
Display
"localfile" = local data file (eg. https://en.wikipedia.org/wiki/Template:Calendar_date/localfiles/Hanukkah)
"calculator" = user-supplied date calculator
"wikidata" = <tbd> for holidays with their own date entity page such as https://www.wikidata.org/wiki/Q51224536
]]
require('strict')
local p = {}
local cfg -- Data structure from ~/events
local eventdata -- Data structure from ~/localfiles/<holiday name>
local track = {} -- Tracking category container
--[[--------------------------< inlineError >-----------------------
Line 15 ⟶ 24:
local function inlineError(arg, msg, tname)
end
Line 22 ⟶ 31:
--[[--------------------------< trimArg >-----------------------
]]
local function trimArg(arg)
end
local function trimArg2(arg)
end
--[[--------------------------< tableLength >-----------------------
]]
local function tableLength(T)
end
--[[-------------------------< make_wikilink >----------------------------------------------------
Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [ [L|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 == no_link then
if link and ('' ~= link) then
if display and ('' ~= display) then
return table.concat ({'[[', link, '|', display, ']]'});
else
return table.concat ({'[[', link, ']]'});
end
end
else -- no_link
if display and ('' ~= display) then -- if there is display text
return display; -- return that
else
return link or ''; -- return the target article name or empty string
end
end
end
--[[--------------------------< createTracking >-----------------------
]]
Line 62 ⟶ 97:
local function createTracking()
table.insert (out, make_wikilink (key)) -- and convert category names to links
return table.concat (out) -- concat into one big string; empty string if table is empty
end
--[[--------------------------<
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 days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
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 month or month == '' or not day or day == '' then
return false -- something missing
end
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==m) then -- if February
month_length = 28 -- then 28 days unless
if (0==(y%4) and (0~=(y%100) or 0==(y%400))) then -- is a leap year?
month_length = 29 -- if leap year then 29 days in February
end
else
month_length=days_in_month[m];
end
if 1 > d or month_length < d then -- day is within bounds
end
return true
end
--[[--------------------------< makeDate >-----------------------
]]
local function makeDate(year, month, day, df, format)
local formatFull = {
['dmy'] = 'j F Y',
['mdy'] = 'F j, Y',
['ymd'] = 'Y F j',
['iso'] = 'Y-m-d'
}
local formatInfobox = {
['dmy'] = 'j F',
['mdy'] = 'F j',
['ymd'] = 'F j',
['iso'] = 'Y-m-d'
}
local date = table.concat ({year, month, day}) -- assemble iso format date
if format ~= "infobox" then
return mw.getContentLanguage():formatDate (formatFull[df], date)
else
return mw.getContentLanguage():formatDate (formatInfobox[df], date)
end
end
--[[--------------------------< dateOffset >-----------------------
]]
local function dateOffset(origdate, offset)
local year, month, day = origdate:match ('(%d%d%d%d)-(%d%d)-(%d%d)')
local now = os.time{year = year, month = month, day = day}
local newdate = os.date("%Y-%m-%d", now + (tonumber(offset) * 24 * 3600))
return newdate and newdate or origdate
end
--[[--------------------------< renderHoli >-----------------------
]]
local function renderHoli(
local hits = 0
local matchdate = "^" .. date
local startdate,enddate,outoffset,endoutoffset = nil
local starttitle,endtitle = ""
-- user-supplied date calculator
if cfg.datatype == "calculator" then
if cfg.datasource then
startdate = calcdate
enddate = dateOffset(startdate, cfg.days - 1)
else
return inlineError("holiday", 'invalid calculator result', tname )
end
-- read dates from localfile -- it assumes dates are in chrono order, need a more flexible method
elseif cfg.datatype == "localfile" then
local numRecords = tableLength(eventdata) -- Get first and last date of holiday
for i = 1, numRecords do
if mw.ustring.find( eventdata[i].date, matchdate ) then
if hits == 0 then
startdate = eventdata[i].date
hits = 1
end
if hits >= tonumber(cfg.days) then
enddate = eventdata[i].date
break
end
hits
end
end
if cfg.name == "Hanukkah"
elseif cfg.datatype == "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
cfg.days =
end
endoutoffset =
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 or enddate == nil then return nil end
year, month,
local leader = ((format == "infobox") and "<br>") or " "
endoutoffset = leader .. "(" .. makeDate(year, month, day, df, "infobox") .. " outside of Israel)"
end
if not endoutoffset then
endoutoffset = ""
end
format =
--- Determine pre-pended text string eg. "sunset, <date>"
local prepend1 = (cfg.prepend1 and (cfg.prepend1 .. ", ")) or ""
local prepend2 = (cfg.prepend2 and (cfg.prepend2 .. ", ")) or ""
-- return output
if startdate == enddate or cfg.days == "1" then -- single date
return prepend1 .. startdate .. endoutoffset .. cite
else
return prepend1 .. startdate .. format .. prepend2 .. enddate .. endoutoffset .. cite
end
end
Line 311 ⟶ 304:
function p.calendardate(frame)
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
return inlineError("year", 'missing year argument', tname) .. createTracking()
elseif not isValidDate(date, "01", "01") 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 == "localfile" then
local eventfile = nil
eventfile = mw.loadData(cfg.datasource)
if eventfile.event then
eventdata = eventfile.event
else
return inlineError("holiday", 'unknown holiday file ' .. cfg.datasource .. '</span>', tname) .. createTracking()
end
-- If datatype = calculator
elseif cfg.datatype == "calculator" then
calcdate = frame:preprocess(cfg.datasource:gsub("YYYY", date))
local year, month, day = calcdate:match ('(%d%d%d%d)-(%d%d)-(%d%d)')
if not isValidDate(year, month, day) then
return inlineError("holiday", 'invalid calculated date ' .. calcdate, tname) .. createTracking()
end
else
return inlineError("holiday", 'unknown "datatype" in configuration', tname) .. createTracking()
end
--- Determine df - priority to |df in template, otherwise df in datafile, otherwise default to dmy
if not
df = (cfg.df and cfg.df) or "dmy"
end
if df ~= "mdy" and df ~= "dmy" and df ~= "iso" then
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 == nil then
citetitle = 'Dates for ' .. cfg.name
end
cite = frame:preprocess('<ref name="' .. holiday .. ' dates">{{cite web |url=' .. cfg.citeurl .. ' |title=' .. citetitle .. ' |publisher=' .. cfg.source .. '|accessdate=' .. cfg.accessdate .. '}}</ref>')
elseif cfg.source then
cite = frame:preprocess('<ref name="' .. holiday .. ' dates">' .. cfg.source:gsub("YYYY", date) .. '</ref>')
else
cite = ""
end
else
cite = ""
end
else
cite = ""
end
end
|