Модуль:Wikidata/Даты2
Поделись знанием:
Для документации этого модуля может быть создана страница Модуль: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