Jump to content
Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Since 7 October 2026 every request to landrace.wiki passes through Cloudflare, a security service brought in after a denial-of-service attack made the site unreachable. The Privacy policy now explains what this means for your data.

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

--[[
Normalise an accession date parameter before Semantic MediaWiki stores it.

Many accession pages write dates day-first, as dd/mm/yyyy. SMW reads an ambiguous nn/nn/yyyy
month-first, so 03/09/2023 (3 September 2023) was stored as 9 March 2023. It reads an unambiguous
15/09/2023 correctly.

iso() rewrites a valid day-first d/m/yyyy or dd/mm/yyyy as yyyy-mm-dd, which SMW cannot misread.
It returns every other value unchanged: ISO dates, years, prose such as "Early 1990s", and a slash
date that is not a valid day-first date, which SMW then reads exactly as it did before.

display() gives the same date in words for the infobox: "3 September 2023", or "April 2023" for a
year and month. It returns anything else unchanged.

Used by Template:Accession for Has collection date, Has sample harvest date and Has eradication
date. Pass the value as 1=, never positionally: a positional value containing "=" would vanish.
]]
local p = {}

local DAYS_IN_MONTH = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
local MONTH_NAMES = { 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
	'September', 'October', 'November', 'December' }

local function isValidDate(y, m, d)
	if m < 1 or m > 12 or d < 1 then
		return false
	end
	local last = DAYS_IN_MONTH[m]
	if m == 2 and y % 4 == 0 and (y % 100 ~= 0 or y % 400 == 0) then
		last = 29
	end
	return d <= last
end

function p._iso(value)
	value = mw.text.trim(value or '')
	local d, m, y = value:match('^(%d%d?)/(%d%d?)/(%d%d%d%d)$')
	if d then
		d, m, y = tonumber(d), tonumber(m), tonumber(y)
		if isValidDate(y, m, d) then
			return string.format('%04d-%02d-%02d', y, m, d)
		end
	end
	return value
end

function p._display(value)
	local iso = p._iso(value)
	local y, m, d = iso:match('^(%d%d%d%d)%-(%d%d)%-(%d%d)$')
	if y then
		y, m, d = tonumber(y), tonumber(m), tonumber(d)
		if isValidDate(y, m, d) then
			return string.format('%d %s %d', d, MONTH_NAMES[m], y)
		end
		return iso
	end
	y, m = iso:match('^(%d%d%d%d)%-(%d%d)$')
	if y then
		m = tonumber(m)
		if m >= 1 and m <= 12 then
			return MONTH_NAMES[m] .. ' ' .. y
		end
	end
	return iso
end

function p.iso(frame)
	return p._iso(frame.args[1])
end

function p.display(frame)
	return p._display(frame.args[1])
end

return p