79/107 successes

input occurrences output expected error
{{J2G|30 August 1585}} 39 ??? Module:time/sandbox:12: Timestamp '{{J2G|30 August 1585}}' could not be parsed; see the documentation for the #time parser function).
February 10 2024 February 25 ???
September 30 8 2024 September 30 ???
February 24,2016 2016 5 2016 February 24 ???
{{J2G|2 January 1579}} 5 ??? Module:time/sandbox:12: Timestamp '{{J2G|2 January 1579}}' could not be parsed; see the documentation for the #time parser function).
15 Jul 2010 2010 2 2010 July 15 ???
20 December1806 2 1806 December 20 ???
17.03.19 2 2024 May 25 ???
n.d. 2 2024 May 25 ???
October 2 2 2024 October 2 ???
September 29, 1905 1905 2 1905 September 29 ???
9 September 9 2005 1 2009 September 9 ???
1 March 1, 1988 1 1988 March 1 ???
1 September1870 1 1870 September 1 ???
4/11/03 2003 1 2003 April 11 ???
27 January 27 2010 1 2027 January 27 ???
25 February 1996. 1 1996 February 25 ???
05-2-27 1 2005 February 27 ???
30.6.2011-06-30 1 2011 June 30 ???
11/19, 2015 1 2024 November 19 November 19
2011, October 7th 1 2011 October 7 Module:time/sandbox:12: Timestamp '2011 October 7th' could not be parsed; see the documentation for the #time parser function).
1974-5 1 1974 May 1 1974 May
2005...2011 1 2011 May 25 ???
March 23, 1658-9 1 1658 March 23 1658-9 March 23
February 2010 2010 1 2010 February 1 ???
September 2003, 2003 1 2003 September 1 ???
Wed, 28 Feb 2001 2001 1 2001 February 28 ???
January20, 2010 1 2010 January 20 ???

local export = {}


local language = mw.getContentLanguage()
local function format(code, timestamp)
	local ok, date = pcall(language.formatDate, language, code, timestamp)
	if ok then
		return date
	else
		-- All the formats used in quote_impl are fine,
		-- so the timestamp must be at fault.
		error("Timestamp '" .. tostring(timestamp) .. "' could not be parsed; "
			.. "see the [[mw:Help:Extension:ParserFunctions##time|"
			.. "documentation for the #time parser function"
			.. "]]).")
	end
end

local sub = mw.ustring.sub
local gsub = mw.ustring.gsub


local abbrs = {
	["a."] = { anchor = "a.", full = "ante", },
	["c."] = { anchor = "c.", full = "circa", },
	["p."] = { anchor = "p.", full = "post", },
}


-- The formatDate method of the mw.language object behaves like the {{#time:}}
-- parser function, which doesn't accept the formats
-- "monthday monthname, year" or "year monthname monthday",
-- but outputs garbage when it receives them, behavior inherited from PHP.
-- {{#formatdate:}} magic word is more forgiving.
-- Fix dates so that, for instance, the |date= parameter of
-- {{quote-journal}} (which uses this module) and the |accessdate=
-- parameter (which uses {{#formatdate:}}) accept similar date formats.
-- [[mw:Extension:Scribunto/Lua_reference_manual#mw.language:formatDate]]
-- [[mw:Help:Extension:ParserFunctions##time]]
-- [[mw:Help:Magic_words#Formatting]]
local function fix_date(date)
	if tonumber(date) ~= nil then
		error("|date= parameter should contain a full date: year, month, day of month. "
			.. "Use |year= parameter for year.")
	end
	if date then
		date = gsub(date, ",%s+", " ")
		date = gsub(date, "^(%d%d%d%d),? +(%a+ +%d%d?)$", "%2 %1")
		date = gsub(date, "^(%d%d%d%d),? +(%d%d?) +(%a+)$", "%3 %2 %1")
		return date
	end
end


local function maintenance_line(text)
	return "<span class=\"maintenance-line\" style=\"color: #777777;\">(" .. text .. ")</span>"
end


function export.quote(frame)
	local params = {
		["year"] = {},
		["month"] = {},
		["date"] = {},
		["start_date"] = {},
		["start_year"] = {},
		["nodate"] = { type = boolean, default = false },
		["accessdate"] = {},
		["origdate"] = {},
		["origyear"] = {},
		["origmonth"] = {},
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params, true)
	return export.quote_impl(args)
end

function export.quote_impl(args)	
	local output = {}
	local namespace = mw.title.getCurrentTitle().nsText
	
	local start_date, date = fix_date(args.start_date), fix_date(args.date)
	
	local function insert(text)
		table.insert(output, text)
	end
	
	local year = args.year
	
	if year then
		local prefix = sub(year, 1, 2)
		local abbr = abbrs[prefix]
		
		if abbr then
			insert('\'\'[[Appendix:Glossary#' .. abbr.anchor .. '|<abbr title="' .. abbr.full .. '">' .. abbr.anchor .. '</abbr>]]\'\' ')
			-- [[Special:WhatLinksHere/Wiktionary:Tracking/quote/abbr]]
			require("Module:debug").track("quote/abbr")
			
			-- Remove lowercase letter, period, and space from beginning of year parameter.
			year = gsub(year, "^%l%.%s*", "")
		end
		
		if start_date then
			if format("Y", start_date) == year then
				if format("F", start_date) == args.month then
					insert(
						format("'''Y''' F j", start_date)
							.. "–" .. date
					)
				else
					insert(
						format("'''Y''' F j",
							start_date)
							.. " – " .. args.month .. " " .. date
					)
				end
			end
		else
			if args.month then
				if args.start_year then
					insert(
						"'''" .. args.start_year
						.. "'''&nbsp;– "
					)
				end
				
				insert(
					"'''" .. year .. "''' "
					.. args.month
				)
				
				if date then
					insert(" " .. date)
				end
			else
				if args.start_year then
					insert("'''" .. args.start_year .. "'''–")
				end
				
				insert("'''" .. year .. "'''")
			end
		end
	else
		if date then
			-- WARNING! This just ignores start_date.
			if date:find "^%d%d%d%d%-%d%d$"
			or date:find "^%a+,? +%d%d%d%d$"
			or date:find "^%d%d%d%d,? +%a+$" then
				insert(format("'''Y''' F", date))
			elseif start_date then
				if format("Y", start_date) == format("Y", date) then
					if format("n", start_date) == format("n", date) then
						insert(
							format("'''Y''' F j", start_date)
								.. "–" .. format("j", date)
						)
					else
						insert(
							format("'''Y''' F j", start_date)
								.. "–" .. format("F j", date)
						)
					end
				else
					insert(
						format("'''Y''' F j", start_date)
							.. "–" .. format("'''Y''' F j", date)
					)
				end
			else
				insert(
					format("'''Y''' F j", date)
				)
			end
		else
			if not args.nodate then
				if args.accessdate then
					insert(
						format("'''Y''' F j", args.accessdate)
						.. " (last accessed)"
					)
				else
					if namespace ~= "Template" then
						insert(
							maintenance_line("Can we [[:Category:Requests for date|date]] this quote?") ..
							"[[Category:Requests for date]]"
						)
					end
				end
			end
		end
	end

	return table.concat(output)
end

return export