<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://the-democratika.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ADate_table_sorting</id>
	<title>Module:Date table sorting - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://the-democratika.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ADate_table_sorting"/>
	<link rel="alternate" type="text/html" href="https://the-democratika.com/wiki/index.php?title=Module:Date_table_sorting&amp;action=history"/>
	<updated>2026-04-05T06:09:34Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://the-democratika.com/wiki/index.php?title=Module:Date_table_sorting&amp;diff=8313&amp;oldid=prev</id>
		<title>&gt;Nardog: per move</title>
		<link rel="alternate" type="text/html" href="https://the-democratika.com/wiki/index.php?title=Module:Date_table_sorting&amp;diff=8313&amp;oldid=prev"/>
		<updated>2019-07-10T15:00:29Z</updated>

		<summary type="html">&lt;p&gt;per move&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local yesno = require(&amp;#039;Module:Yesno&amp;#039;)&lt;br /&gt;
local lang = mw.language.getContentLanguage()&lt;br /&gt;
local N_YEAR_DIGITS = 12&lt;br /&gt;
local MAX_YEAR = 10^N_YEAR_DIGITS - 1&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Dts class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Dts = {}&lt;br /&gt;
Dts.__index = Dts&lt;br /&gt;
&lt;br /&gt;
Dts.months = {&lt;br /&gt;
	&amp;quot;January&amp;quot;,&lt;br /&gt;
	&amp;quot;February&amp;quot;,&lt;br /&gt;
	&amp;quot;March&amp;quot;,&lt;br /&gt;
	&amp;quot;April&amp;quot;,&lt;br /&gt;
	&amp;quot;May&amp;quot;,&lt;br /&gt;
	&amp;quot;June&amp;quot;,&lt;br /&gt;
	&amp;quot;July&amp;quot;,&lt;br /&gt;
	&amp;quot;August&amp;quot;,&lt;br /&gt;
	&amp;quot;September&amp;quot;,&lt;br /&gt;
	&amp;quot;October&amp;quot;,&lt;br /&gt;
	&amp;quot;November&amp;quot;,&lt;br /&gt;
	&amp;quot;December&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Dts.monthsAbbr = {&lt;br /&gt;
	&amp;quot;Jan&amp;quot;,&lt;br /&gt;
	&amp;quot;Feb&amp;quot;,&lt;br /&gt;
	&amp;quot;Mar&amp;quot;,&lt;br /&gt;
	&amp;quot;Apr&amp;quot;,&lt;br /&gt;
	&amp;quot;May&amp;quot;,&lt;br /&gt;
	&amp;quot;Jun&amp;quot;,&lt;br /&gt;
	&amp;quot;Jul&amp;quot;,&lt;br /&gt;
	&amp;quot;Aug&amp;quot;,&lt;br /&gt;
	&amp;quot;Sep&amp;quot;,&lt;br /&gt;
	&amp;quot;Oct&amp;quot;,&lt;br /&gt;
	&amp;quot;Nov&amp;quot;,&lt;br /&gt;
	&amp;quot;Dec&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function Dts._makeMonthSearch(t)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for i, month in ipairs(t) do&lt;br /&gt;
		ret[month:lower()] = i&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
Dts.monthSearch = Dts._makeMonthSearch(Dts.months)&lt;br /&gt;
Dts.monthSearchAbbr = Dts._makeMonthSearch(Dts.monthsAbbr)&lt;br /&gt;
Dts.monthSearchAbbr[&amp;#039;sept&amp;#039;] = 9 -- Allow &amp;quot;Sept&amp;quot; to match September&lt;br /&gt;
&lt;br /&gt;
Dts.formats = {&lt;br /&gt;
	dmy = true,&lt;br /&gt;
	mdy = true,&lt;br /&gt;
	dm = true,&lt;br /&gt;
	md = true,&lt;br /&gt;
	my = true,&lt;br /&gt;
	y = true,&lt;br /&gt;
	m = true,&lt;br /&gt;
	d = true,&lt;br /&gt;
	hide = true&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function Dts.new(args)&lt;br /&gt;
	local self = setmetatable({}, Dts)&lt;br /&gt;
&lt;br /&gt;
	-- Parse date parameters.&lt;br /&gt;
	-- In this step we also record whether the date was in DMY or YMD format,&lt;br /&gt;
	-- and whether the month name was abbreviated.&lt;br /&gt;
	if args[2] or args[3] or args[4] then&lt;br /&gt;
		self:parseDateParts(args[1], args[2], args[3], args[4])&lt;br /&gt;
	elseif args[1] then&lt;br /&gt;
		self:parseDate(args[1])&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Raise an error on invalid values&lt;br /&gt;
	if self.year then&lt;br /&gt;
		if self.year == 0 then&lt;br /&gt;
			error(&amp;#039;years cannot be zero&amp;#039;, 0)&lt;br /&gt;
		elseif self.year &amp;lt; -MAX_YEAR then&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;#039;years cannot be less than %s&amp;#039;,&lt;br /&gt;
				lang:formatNum(-MAX_YEAR)&lt;br /&gt;
			), 0)&lt;br /&gt;
		elseif self.year &amp;gt; MAX_YEAR then&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;#039;years cannot be greater than %s&amp;#039;,&lt;br /&gt;
				lang:formatNum(MAX_YEAR)&lt;br /&gt;
			), 0)&lt;br /&gt;
		elseif math.floor(self.year) ~= self.year then&lt;br /&gt;
			error(&amp;#039;years must be an integer&amp;#039;, 0)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if self.month and (&lt;br /&gt;
		self.month &amp;lt; 1&lt;br /&gt;
		or self.month &amp;gt; 12&lt;br /&gt;
		or math.floor(self.month) ~= self.month&lt;br /&gt;
	) then&lt;br /&gt;
		error(&amp;#039;months must be an integer between 1 and 12&amp;#039;, 0)&lt;br /&gt;
	end&lt;br /&gt;
	if self.day and (&lt;br /&gt;
		self.day &amp;lt; 1&lt;br /&gt;
		or self.day &amp;gt; 31&lt;br /&gt;
		or math.floor(self.day) ~= self.day&lt;br /&gt;
	) then&lt;br /&gt;
		error(&amp;#039;days must be an integer between 1 and 31&amp;#039;, 0)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set month abbreviation behaviour, i.e. whether we are outputting&lt;br /&gt;
	-- &amp;quot;January&amp;quot; or &amp;quot;Jan&amp;quot;.&lt;br /&gt;
	if args.abbr then&lt;br /&gt;
		self.isAbbreviated = args.abbr == &amp;#039;on&amp;#039; or yesno(args.abbr) or false&lt;br /&gt;
	else&lt;br /&gt;
		self.isAbbreviated = self.isAbbreviated or false&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set the format string&lt;br /&gt;
	if args.format then&lt;br /&gt;
		self.format = args.format&lt;br /&gt;
	else&lt;br /&gt;
		self.format = self.format or &amp;#039;mdy&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if not Dts.formats[self.format] then&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&amp;quot;&amp;#039;%s&amp;#039; is not a valid format&amp;quot;,&lt;br /&gt;
			tostring(self.format)&lt;br /&gt;
		), 0)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set addkey. This adds a value at the end of the sort key, allowing users&lt;br /&gt;
	-- to manually distinguish between identical dates.&lt;br /&gt;
	if args.addkey then&lt;br /&gt;
		self.addkey = tonumber(args.addkey)&lt;br /&gt;
		if not self.addkey or&lt;br /&gt;
			self.addkey &amp;lt; 0 or&lt;br /&gt;
			self.addkey &amp;gt; 9999 or&lt;br /&gt;
			math.floor(self.addkey) ~= self.addkey&lt;br /&gt;
		then&lt;br /&gt;
			error(&amp;quot;the &amp;#039;addkey&amp;#039; parameter must be an integer between 0 and 9999&amp;quot;, 0)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set whether the displayed date is allowed to wrap or not.&lt;br /&gt;
	self.isWrapping = args.nowrap == &amp;#039;off&amp;#039; or yesno(args.nowrap) == false&lt;br /&gt;
&lt;br /&gt;
	return self&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Dts:hasDate()&lt;br /&gt;
	return (self.year or self.month or self.day) ~= nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Find the month number for a month name, and set the isAbbreviated flag as&lt;br /&gt;
-- appropriate.&lt;br /&gt;
function Dts:parseMonthName(s)&lt;br /&gt;
	s = s:lower()&lt;br /&gt;
	local month = Dts.monthSearch[s]&lt;br /&gt;
	if month then&lt;br /&gt;
		return month&lt;br /&gt;
	else&lt;br /&gt;
		month = Dts.monthSearchAbbr[s]&lt;br /&gt;
		if month then&lt;br /&gt;
			self.isAbbreviated = true&lt;br /&gt;
			return month&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Parses separate parameters for year, month, day, and era.&lt;br /&gt;
function Dts:parseDateParts(year, month, day, bc)&lt;br /&gt;
	if year then&lt;br /&gt;
		self.year = tonumber(year)&lt;br /&gt;
		if not self.year then&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;quot;&amp;#039;%s&amp;#039; is not a valid year&amp;quot;,&lt;br /&gt;
				tostring(year)&lt;br /&gt;
			), 0)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if month then&lt;br /&gt;
		if tonumber(month) then&lt;br /&gt;
			self.month = tonumber(month)&lt;br /&gt;
		elseif type(month) == &amp;#039;string&amp;#039; then&lt;br /&gt;
			self.month = self:parseMonthName(month)&lt;br /&gt;
		end&lt;br /&gt;
		if not self.month then&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;quot;&amp;#039;%s&amp;#039; is not a valid month&amp;quot;,&lt;br /&gt;
				tostring(month)&lt;br /&gt;
			), 0)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if day then&lt;br /&gt;
		self.day = tonumber(day)&lt;br /&gt;
		if not self.day then&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;quot;&amp;#039;%s&amp;#039; is not a valid day&amp;quot;,&lt;br /&gt;
				tostring(day)&lt;br /&gt;
			), 0)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if bc then&lt;br /&gt;
		local bcLower = type(bc) == &amp;#039;string&amp;#039; and bc:lower()&lt;br /&gt;
		if bcLower == &amp;#039;bc&amp;#039; or bcLower == &amp;#039;bce&amp;#039; then&lt;br /&gt;
			if self.year and self.year &amp;gt; 0 then&lt;br /&gt;
				self.year = -self.year&lt;br /&gt;
			end&lt;br /&gt;
		elseif bcLower ~= &amp;#039;ad&amp;#039; and bcLower ~= &amp;#039;ce&amp;#039; then&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;quot;&amp;#039;%s&amp;#039; is not a valid era code (expected &amp;#039;BC&amp;#039;, &amp;#039;BCE&amp;#039;, &amp;#039;AD&amp;#039; or &amp;#039;CE&amp;#039;)&amp;quot;,&lt;br /&gt;
				tostring(bc)&lt;br /&gt;
			), 0)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- This method parses date strings. This is a poor man&amp;#039;s alternative to&lt;br /&gt;
-- mw.language:formatDate, but it ends up being easier for us to parse the date&lt;br /&gt;
-- here than to use mw.language:formatDate and then try to figure out after the&lt;br /&gt;
-- fact whether the month was abbreviated and whether we were DMY or MDY.&lt;br /&gt;
function Dts:parseDate(date)&lt;br /&gt;
	-- Generic error message.&lt;br /&gt;
	local function dateError()&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&amp;quot;&amp;#039;%s&amp;#039; is an invalid date&amp;quot;,&lt;br /&gt;
			date&lt;br /&gt;
		), 0)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function parseDayOrMonth(s)&lt;br /&gt;
		if s:find(&amp;#039;^%d%d?$&amp;#039;) then&lt;br /&gt;
			return tonumber(s)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function parseYear(s)&lt;br /&gt;
		if s:find(&amp;#039;^%d%d%d%d?$&amp;#039;) then&lt;br /&gt;
			return tonumber(s)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Deal with year-only dates first, as they can have hyphens in, and later&lt;br /&gt;
	-- we need to split the string by all non-word characters, including&lt;br /&gt;
	-- hyphens. Also, we don&amp;#039;t need to restrict years to 3 or 4 digits, as on&lt;br /&gt;
	-- their own they can&amp;#039;t be confused as a day or a month number.&lt;br /&gt;
	self.year = tonumber(date)&lt;br /&gt;
	if self.year then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Split the string using non-word characters as boundaries.&lt;br /&gt;
	date = tostring(date)&lt;br /&gt;
	local parts = mw.text.split(date, &amp;#039;%W+&amp;#039;)&lt;br /&gt;
	local nParts = #parts&lt;br /&gt;
	if parts[1] == &amp;#039;&amp;#039; or parts[nParts] == &amp;#039;&amp;#039; or nParts &amp;gt; 3 then&lt;br /&gt;
		-- We are parsing a maximum of three elements, so raise an error if we&lt;br /&gt;
		-- have more. If the first or last elements were blank, then the start&lt;br /&gt;
		-- or end of the string was a non-word character, which we will also&lt;br /&gt;
		-- treat as an error.&lt;br /&gt;
		dateError()&lt;br /&gt;
	elseif nParts &amp;lt; 1 then&lt;br /&gt;
	 	-- If we have less than one element, then something has gone horribly&lt;br /&gt;
	 	-- wrong.&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&amp;quot;an unknown error occurred while parsing the date &amp;#039;%s&amp;#039;&amp;quot;,&lt;br /&gt;
			date&lt;br /&gt;
		), 0)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if nParts == 1 then&lt;br /&gt;
		-- This can be either a month name or a year.&lt;br /&gt;
		self.month = self:parseMonthName(parts[1])&lt;br /&gt;
		if not self.month then&lt;br /&gt;
			self.year = parseYear(parts[1])&lt;br /&gt;
			if not self.year then&lt;br /&gt;
				dateError()&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	elseif nParts == 2 then&lt;br /&gt;
		-- This can be any of the following formats:&lt;br /&gt;
		-- DD Month&lt;br /&gt;
		-- Month DD&lt;br /&gt;
		-- Month YYYY&lt;br /&gt;
		-- YYYY-MM&lt;br /&gt;
		self.month = self:parseMonthName(parts[1])&lt;br /&gt;
		if self.month then&lt;br /&gt;
			-- This is either Month DD or Month YYYY.&lt;br /&gt;
			self.year = parseYear(parts[2])&lt;br /&gt;
			if not self.year then&lt;br /&gt;
				-- This is Month DD.&lt;br /&gt;
				self.format = &amp;#039;mdy&amp;#039;&lt;br /&gt;
				self.day = parseDayOrMonth(parts[2])&lt;br /&gt;
				if not self.day then&lt;br /&gt;
					dateError()&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			self.month = self:parseMonthName(parts[2])&lt;br /&gt;
			if self.month then&lt;br /&gt;
				-- This is DD Month.&lt;br /&gt;
				self.format = &amp;#039;dmy&amp;#039;&lt;br /&gt;
				self.day = parseDayOrMonth(parts[1])&lt;br /&gt;
				if not self.day then&lt;br /&gt;
					dateError()&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				-- This is YYYY-MM.&lt;br /&gt;
				self.year = parseYear(parts[1])&lt;br /&gt;
				self.month = parseDayOrMonth(parts[2])&lt;br /&gt;
				if not self.year or not self.month then&lt;br /&gt;
					dateError()&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	elseif nParts == 3 then&lt;br /&gt;
		-- This can be any of the following formats:&lt;br /&gt;
		-- DD Month YYYY&lt;br /&gt;
		-- Month DD, YYYY&lt;br /&gt;
		-- YYYY-MM-DD&lt;br /&gt;
		-- DD-MM-YYYY&lt;br /&gt;
		self.month = self:parseMonthName(parts[1])&lt;br /&gt;
		if self.month then&lt;br /&gt;
			-- This is Month DD, YYYY.&lt;br /&gt;
			self.format = &amp;#039;mdy&amp;#039;&lt;br /&gt;
			self.day = parseDayOrMonth(parts[2])&lt;br /&gt;
			self.year = parseYear(parts[3])&lt;br /&gt;
			if not self.day or not self.year then&lt;br /&gt;
				dateError()&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			self.day = parseDayOrMonth(parts[1])&lt;br /&gt;
			if self.day then&lt;br /&gt;
				self.month = self:parseMonthName(parts[2])&lt;br /&gt;
				if self.month then&lt;br /&gt;
					-- This is DD Month YYYY.&lt;br /&gt;
					self.format = &amp;#039;dmy&amp;#039;&lt;br /&gt;
					self.year = parseYear(parts[3])&lt;br /&gt;
					if not self.year then&lt;br /&gt;
						dateError()&lt;br /&gt;
					end&lt;br /&gt;
				else&lt;br /&gt;
					-- This is DD-MM-YYYY.&lt;br /&gt;
					self.format = &amp;#039;dmy&amp;#039;&lt;br /&gt;
					self.month = parseDayOrMonth(parts[2])&lt;br /&gt;
					self.year = parseYear(parts[3])&lt;br /&gt;
					if not self.month or not self.year then&lt;br /&gt;
						dateError()&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				-- This is YYYY-MM-DD&lt;br /&gt;
				self.year = parseYear(parts[1])&lt;br /&gt;
				self.month = parseDayOrMonth(parts[2])&lt;br /&gt;
				self.day = parseDayOrMonth(parts[3])&lt;br /&gt;
				if not self.year or not self.month or not self.day then&lt;br /&gt;
					dateError()&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Dts:makeSortKey()&lt;br /&gt;
	local year, month, day&lt;br /&gt;
	local nYearDigits = N_YEAR_DIGITS&lt;br /&gt;
	if self:hasDate() then&lt;br /&gt;
		year = self.year or os.date(&amp;quot;*t&amp;quot;).year&lt;br /&gt;
		if year &amp;lt; 0 then&lt;br /&gt;
			year = -MAX_YEAR - 1 - year&lt;br /&gt;
			nYearDigits = nYearDigits + 1 -- For the minus sign&lt;br /&gt;
		end&lt;br /&gt;
		month = self.month or 1&lt;br /&gt;
		day = self.day or 1&lt;br /&gt;
	else&lt;br /&gt;
		-- Blank {{dts}} transclusions should sort last.&lt;br /&gt;
		year = MAX_YEAR&lt;br /&gt;
		month = 99&lt;br /&gt;
		day = 99&lt;br /&gt;
	end&lt;br /&gt;
	return string.format(&lt;br /&gt;
		&amp;#039;%0&amp;#039; .. nYearDigits .. &amp;#039;d-%02d-%02d-%04d&amp;#039;,&lt;br /&gt;
		year, month, day, self.addkey or 0&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Dts:getMonthName()&lt;br /&gt;
	if not self.month then&lt;br /&gt;
		return &amp;#039;&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if self.isAbbreviated then&lt;br /&gt;
		return self.monthsAbbr[self.month]&lt;br /&gt;
	else&lt;br /&gt;
		return self.months[self.month]&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Dts:makeDisplay()&lt;br /&gt;
	if self.format == &amp;#039;hide&amp;#039; then&lt;br /&gt;
		return &amp;#039;&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	local hasYear = self.year and self.format:find(&amp;#039;y&amp;#039;)&lt;br /&gt;
	local hasMonth = self.month and self.format:find(&amp;#039;m&amp;#039;)&lt;br /&gt;
	local hasDay = self.day and self.format:find(&amp;#039;d&amp;#039;)&lt;br /&gt;
	local isMonthFirst = self.format:find(&amp;#039;md&amp;#039;)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	if hasDay and hasMonth and isMonthFirst then&lt;br /&gt;
		ret[#ret + 1] = self:getMonthName()&lt;br /&gt;
		ret[#ret + 1] = &amp;#039; &amp;#039;&lt;br /&gt;
		ret[#ret + 1] = self.day&lt;br /&gt;
		if hasYear then&lt;br /&gt;
			ret[#ret + 1] = &amp;#039;,&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	elseif hasDay and hasMonth then&lt;br /&gt;
		ret[#ret + 1] = self.day&lt;br /&gt;
		ret[#ret + 1] = &amp;#039; &amp;#039;&lt;br /&gt;
		ret[#ret + 1] = self:getMonthName()&lt;br /&gt;
	elseif hasDay then&lt;br /&gt;
		ret[#ret + 1] = self.day&lt;br /&gt;
	elseif hasMonth then&lt;br /&gt;
		ret[#ret + 1] = self:getMonthName()&lt;br /&gt;
	end&lt;br /&gt;
	if hasYear then&lt;br /&gt;
		if hasDay or hasMonth then&lt;br /&gt;
			ret[#ret + 1] = &amp;#039; &amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		local displayYear = math.abs(self.year)&lt;br /&gt;
		if displayYear &amp;gt; 9999 then&lt;br /&gt;
			displayYear = lang:formatNum(displayYear)&lt;br /&gt;
		else&lt;br /&gt;
			displayYear = tostring(displayYear)&lt;br /&gt;
		end&lt;br /&gt;
		ret[#ret + 1] = displayYear&lt;br /&gt;
		if self.year &amp;lt; 0 then&lt;br /&gt;
			ret[#ret + 1] = &amp;#039;&amp;amp;nbsp;BC&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(ret)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Dts:__tostring()&lt;br /&gt;
	local root = mw.html.create()&lt;br /&gt;
	local span = root:tag(&amp;#039;span&amp;#039;)&lt;br /&gt;
		:attr(&amp;#039;data-sort-value&amp;#039;, self:makeSortKey())&lt;br /&gt;
&lt;br /&gt;
	-- Display&lt;br /&gt;
	if self:hasDate() and self.format ~= &amp;#039;hide&amp;#039; then&lt;br /&gt;
		span:wikitext(self:makeDisplay())&lt;br /&gt;
		if not self.isWrapping then&lt;br /&gt;
			span:css(&amp;#039;white-space&amp;#039;, &amp;#039;nowrap&amp;#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exports&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p._exportClasses()&lt;br /&gt;
	return {&lt;br /&gt;
		Dts = Dts&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
	local success, ret = pcall(function ()&lt;br /&gt;
		local dts = Dts.new(args)&lt;br /&gt;
		return tostring(dts)&lt;br /&gt;
	end)&lt;br /&gt;
	if success then&lt;br /&gt;
		return ret&lt;br /&gt;
	else&lt;br /&gt;
		ret = string.format(&lt;br /&gt;
			&amp;#039;&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;Error in [[Template:Date table sorting]]: %s&amp;lt;/strong&amp;gt;&amp;#039;,&lt;br /&gt;
			ret&lt;br /&gt;
		)&lt;br /&gt;
		if mw.title.getCurrentTitle().namespace == 0 then&lt;br /&gt;
			-- Only categorise in the main namespace&lt;br /&gt;
			ret = ret .. &amp;#039;[[Category:Date table sorting templates with errors]]&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		return ret&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = require(&amp;#039;Module:Arguments&amp;#039;).getArgs(frame, {&lt;br /&gt;
		wrappers = &amp;#039;Template:Date table sorting&amp;#039;,&lt;br /&gt;
	})&lt;br /&gt;
	return p._main(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>&gt;Nardog</name></author>
	</entry>
</feed>