Для документации этого модуля может быть создана страница Модуль:Wikidata/Даты2/doc

function nominativeYear( year )
    if ( year >= 0 ) then
        return '[[' .. year .. ' кизонь|' .. year
    else
        return '[[' .. ( 0 - year ) .. ' кизонь м. п. и.|' .. ( 0 - year ) .. ' м. п. и.]]'
    end
end

function formatWiki( time, infocardClass, categoryNamePrefix )
	if 'table'==type( time ) then
		if time.args and time.args[1] then
			time = tonumber( time.args[1] )
		else
			return 'unknown argument type: ' .. type( time ) .. ': ' .. table.tostring( time )
		end
	end
	local t = os.date("*t", time)
	if time < g2uBoundary1 then
		-- выводим просто юлианский календарь. Задавать тут григорианский некорректно
		return p.formatWikiImpl( t, t, infocardClass, categoryNamePrefix )
	end
 
	-- Специальные даты
	if t.year == 1700 and t.month == 3 and t.day == 11 then
		return p.formatWikiImpl( {year=1700, month=2, day=29}, t, infocardClass, categoryNamePrefix)
	end
	if t.year == 1800 and t.month == 3 and t.day == 12 then
		return p.formatWikiImpl( {year=1800, month=2, day=29}, t, infocardClass, categoryNamePrefix )
	end
	if t.year == 1900 and t.month == 3 and t.day == 13 then
		return p.formatWikiImpl( {year=1900, month=2, day=29}, t, infocardClass, categoryNamePrefix )
	end
 
	if g2uBoundary1 <= time and time < g2uBoundary2 then
		return p.formatWikiImpl( os.date("*t", time - 10 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
	end
	if g2uBoundary2 <= time and time < g2uBoundary3 then
		return p.formatWikiImpl( os.date("*t", time - 11 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
	end
	if g2uBoundary3 <= time and time < g2uBoundary4 then
		return p.formatWikiImpl( os.date("*t", time - 12 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
	end
	if g2uBoundary4 <= time and time < g2uBoundary5 then
		return p.formatWikiImpl( os.date("*t", time - 13 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix )
	end
 
	--только Григорианский календарь
	return p.formatWikiImpl( t, t, infocardClass, categoryNamePrefix )
end

function ternary ( cond , T , F )
    if cond then return T else return F end
end

local nominativeMonthes = {'январьгов', 'февральков', 'марков', 'апрельков', 'майгов', 'июньков',
    'июльков', 'августков', 'сентябрьков', 'октябрьков', 'ноябрьков', 'декабрьков'}
 
local genitivusMonthes = {'январьста', 'февральста', 'мартста', 'апрельста', 'майста', 'июньста',
    'июльста', 'августста', 'сентябрьста', 'октябрьста', 'ноябрьста', 'декабрьста'}

function inYear( year )
    if ( year >= 0 ) then
        return '' .. year .. ' кизоня'
    else
        return '' .. ( 0 - year) .. ' кизоня м. п. и.'
    end
end

function formatWikiImpl( t1, t2, infocardClass, categoryNamePrefix )
    local nd = t2.day;
    local nm = t2.month;
    local ny = t2.year;
    local od = ternary ( t1.day ~= t2.day , t1.day, nil );
    local om = ternary ( t1.month ~= t2.month , t1.month, nil );
    local oy = ternary ( t1.year ~= t2.year , t1.year, nil );
 
    local template =
        (nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "") ..
        (od ~= nil and "4" or "") .. (om ~= nil and "5" or "") .. (oy ~= nil and "6" or "")
 
    local datePart = '<span style="white-space:nowrap;">'
    if (template == "12") then
        datePart = datePart .. string.format( "[[%d %s]]",
        								nd, genitivusMonthes[nm] )
    elseif (template == "23") then
        datePart = datePart .. string.format( "[[%s]] %s",
        								nominativeMonthes[nm], nominativeYear( ny ) ) .. ' кизоня]]'
    elseif (template == "3") then
        datePart = datePart .. nominativeYear( ny ) .. ' кизонь]]'
    elseif (template == "123") then
        datePart = datePart .. string.format( "[[%d %s]] %s",
                                        nd, genitivusMonthes[nm], nominativeYear( ny ) ) .. ' кизоня]]'
    elseif (template == "124") then
        datePart = datePart .. string.format( "[[%d %s|%d (%d) %s]]",
                                        nd, genitivusMonthes[nm], od, nd, genitivusMonthes[nm] )
    elseif (template == "1234") then
        datePart = datePart .. string.format( "[[%d %s|%d (%d) %s]] %s",
                                        nd, genitivusMonthes[nm], od, nd, genitivusMonthes[nm], nominativeYear( ny ) ) .. ' кизоня]]'
    elseif (template == "1245") then
        datePart = datePart .. string.format( "%d %s ([[%d %s]])",
                                        od, genitivusMonthes[om], nd, genitivusMonthes[nm] )
    elseif (template == "12345") then
        datePart = datePart .. string.format( "%d %s ([[%d %s]]) %s",
                                        od, genitivusMonthes[om], nd, genitivusMonthes[nm], nominativeYear( ny ) ) .. ' кизоня]]'
    elseif (template == "123456") then
        datePart = datePart .. string.format( '%d %s %d</span> <span style="white-space:nowrap;">([[%d %s]] %s)',
                                        od, genitivusMonthes[om], oy, nd, genitivusMonthes[nm], nominativeYear( ny ) ) .. ' кизоня]]'
    else
        datePart = datePart .. 'формат неверен'
    end
    datePart = datePart .. '</span>'
 
    local infocardTemplate =
        (nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "")
 
    return datePart
end

function deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[deepcopy(orig_key)] = deepcopy(orig_value)
        end
        setmetatable(copy, deepcopy(getmetatable(orig)))
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end
 
function formatDate( value, infoclass, categoryPrefix, unknownCategory )
	if value.unknown then
		local result = "''неизвестно''"
		if ( unknownCategory ) then
			result = result .. "[[" .. unknownCategory.. "]]"
		end
		return result
	end
 
	-- year only
	if value.precision == 9 then
		local tCopy = deepcopy( value.structure )
		tCopy.day = nil
		tCopy.month = nil
		return formatWikiImpl(tCopy, tCopy, infoclass, categoryPrefix)
	end
	-- year and month only
	if value.precision == 10 then
		local tCopy = deepcopy( value.structure )
		tCopy.day = nil
		return formatWikiImpl(tCopy, tCopy, infoclass, categoryPrefix)
	end
 
	if (value.calendarmodel == 'gregorian') then
    	return formatWikiImpl( value.structure, value.structure, infocardClass, categoryPrefix )
    else
		return moduleDates.formatWiki( value.time, infoclass, categoryPrefix )
	end
end
 
-- returns table of time+precision values for specified property
function parseProperty ( propertyName )
	local entity = mw.wikibase.getEntity()
	if not entity or not entity.claims or not entity.claims[propertyName] then
		return nil
	end
 
	local result = {}
	for key, value in pairs( entity.claims[propertyName] ) do
		if ( value.mainsnak.snaktype == "value" ) then
			-- The calendar model used for saving the data is always the proleptic Gregorian calendar according to ISO 8601.
			local timeISO6801 = tostring( value.mainsnak.datavalue.value.time )
			local unixtime = parseISO8601( timeISO6801 )
			local structure = os.date("*t", unixtime)
			local precision = tonumber( value.mainsnak.datavalue.value.precision )
			local calendarmodel = 'gregorian';
			if (mw.ustring.find(value.mainsnak.datavalue.value.calendarmodel, 'Q1985786', 1, true)) then
				calendarmodel = 'julian';
			end
			local item = { time=unixtime, structure=structure, precision=precision, calendarmodel=calendarmodel }
			table.insert ( result, item )
		end
		if ( value.mainsnak.snaktype == "somevalue" ) then
			--unknown
			local item = { unknown="unknown" }
			table.insert ( result, item )
		end
	end
	return result
end
 
function parseISO8601Date(str)
	local pattern = "(%-?%d+)%-(%d+)%-(%d+)T"
	local Y, M, D = mw.ustring.match( str, pattern )
	return tonumber(Y), tonumber(M), tonumber(D)
end
 
function parseISO8601Time(str)
	local pattern = "T(%d+):(%d+):(%d+)%Z"
	local H, M, S = mw.ustring.match( str, pattern)
	return tonumber(H), tonumber(M), tonumber(S)
end
 
function parseISO8601Offset(str)
	if str:sub(-1)=="Z" then return 0,0 end -- ends with Z, Zulu time
 
	-- matches ±hh:mm, ±hhmm or ±hh; else returns nils 
	local pattern = "([-+])(%d%d):?(%d?%d?)$"
	local sign, oh, om = mw.ustring.match( str, pattern) 
	sign, oh, om = sign or "+", oh or "00", om or "00"
 
	return tonumber(sign .. oh), tonumber(sign .. om)
end
 
function parseISO8601(str)
	if 'table'==type(str) then
		if str.args and str.args[1] then
			str = '' .. str.args[1]
		else
			return 'unknown argument type: ' .. type( str ) .. ': ' .. table.tostring( str )
		end
	end
	local Y,M,D = parseISO8601Date(str)
	local h,m,s = parseISO8601Time(str)
	local oh,om = parseISO8601Offset(str)
	return tonumber(os.time({year=Y, month=M, day=D, hour=(h+oh), min=(m+om), sec=s}))
end

-- проверка на совпадающие даты с разной моделью календаря
function checkDupDates( t )
	if #t > 1 then
		local removed = false;
		local j = 1;
		-- проверка на совпадающие даты с разной моделью календаря
		while (j <= #t)  do
			local i = 1;
			while (i <= #t)  do
				if i ~= j then
					if (os.time(t[j].structure) == os.time(t[i].structure)) then
						if ((t[j].calendarmodel == 'gregorian') and 
							(t[i].calendarmodel == 'julian')) then
							removed = true;
							break;
						else
							table.remove(t, i)
						end
					else
					  i = i + 1;
					end
				else
					i = i + 1;
				end
			end
			if removed then
				removed = false;
				table.remove(t, j);
			else
				j = j+1;
			end
		end
	end
end

local p = {}

function p.dateOfReleased( )

	local dTable = parseProperty ( "p571" )
 
	if not dTable then
		return ''
	end
	checkDupDates(dTable);

	local result = ''
	for key, value in pairs( dTable ) do
		if result ~= '' then
			result = result .. ' или '
		end
		if ( appendToCategory ) then
			result = result .. formatDate(value, 'dday', 'Куласть ', 'К:Персоналии, чья дата смерти не установлена')
		else
			result = result .. formatDate(value, 'dday', nil, nil )
		end
    end
   
  	return result
end

function p.dateOfCreation( )

	local dTable = parseProperty ( "p577" )
 
	if not dTable then
		return ''
	end
	checkDupDates(dTable);

	local result = ''
	for key, value in pairs( dTable ) do
		if result ~= '' then
			result = result .. ' или '
		end
		result = result .. formatDate(value, 'dday', nil, nil )
    end
   
  	return result
end

return p