Jump to content

Module:Age

From Natural Philosophy Wiki
Revision as of 16:09, 20 July 2026 by ClaudeBot (talk | contribs) (Create missing Module:Age — restores {{age}}, {{death date and age}} and infobox age calculation (fixes 55 pages with script errors))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:Age/doc

-- Module:Age
-- Provides age calculations for {{age}}, {{death date and age}}, {{birth date and age}}
-- and the date handling in {{Infobox person}} / {{Infobox scientist}}.
--
-- Entry point used on this wiki:
--   {{#invoke:age|age_generic|template=age_full_years}}
-- called from Template:Age, whose parent parameters are:
--   1,2,3 = year, month, day of the earlier date
--   4,5,6 = year, month, day of the later date (defaults to today if omitted)

local p = {}

-- Convert a parameter to a number, tolerating whitespace, empty strings and nil.
local function num(v)
	if v == nil then
		return nil
	end
	v = tostring(v):match('^%s*(.-)%s*$')
	if v == '' then
		return nil
	end
	return tonumber(v)
end

-- Whole years elapsed from (y1,m1,d1) to (y2,m2,d2).
local function fullYears(y1, m1, d1, y2, m2, d2)
	local age = y2 - y1
	if (m2 < m1) or (m2 == m1 and d2 < d1) then
		age = age - 1
	end
	return age
end

-- Collect the six date parameters, preferring the parent frame (the template call),
-- falling back to direct #invoke arguments so the module can also be called directly.
local function getDates(frame)
	local args = {}
	local parent = frame:getParent()
	if parent and parent.args then
		for i = 1, 6 do
			args[i] = parent.args[i]
		end
	end
	for i = 1, 6 do
		if num(args[i]) == nil then
			args[i] = frame.args[i] or args[i]
		end
	end

	local y1, m1, d1 = num(args[1]), num(args[2]), num(args[3])
	local y2, m2, d2 = num(args[4]), num(args[5]), num(args[6])

	-- No later date supplied: measure to today.
	if y2 == nil then
		local now = os.date('*t')
		y2, m2, d2 = now.year, now.month, now.day
	end

	-- Missing month/day default to the start of the year, matching the
	-- behaviour the wrapper templates expect when they pass partial dates.
	m1, d1 = m1 or 1, d1 or 1
	m2, d2 = m2 or 1, d2 or 1

	return y1, m1, d1, y2, m2, d2
end

function p.age_generic(frame)
	local y1, m1, d1, y2, m2, d2 = getDates(frame)

	if y1 == nil then
		return ''
	end

	local age = fullYears(y1, m1, d1, y2, m2, d2)

	-- Guard against obviously bad input rather than emitting a negative age.
	if age < 0 or age > 150 then
		return ''
	end

	return tostring(age)
end

-- Aliases, so other standard wrappers work if they are ever imported.
p.age_full_years = p.age_generic
p.main = p.age_generic

return p