Модуль:Wikidata/Даты
Для документации этого модуля может быть создана страница Модуль:Wikidata/Даты/Документация
local moduleDates = require( "Module:Dates" )
local moduleMath = require( "Module:Math" )
local p = {}
--[[
Функция возвращает значения типа "time" данного свойства из Викиданных.
Значения других типов игнорируются.
Если есть значения ранга "preferred", возвращаются именно они,
иначе возвращаются значения ранга "preferred".
Значения ранга "deprecated" игнорируются.
Даты юлианского календаря переводятся в григорианский
]]
function p.parseProperty(s_property_name)
local entity = mw.wikibase.getEntity()
if entity == nil then
return nil
end
if entity.claims == nil then
return nil
end
local claim = entity.claims[s_property_name]
if claim == nil then
return nil
end
local preferred_values = {}
local normal_values = {}
for key, value in pairs(claim) do
local snak = value.mainsnak
local item = nil
if snak.snaktype == "value" and snak.datavalue.type == "time" then
item = {}
item.precision = snak.datavalue.value.precision
if snak.datavalue.value.calendarmodel == "http://www.wikidata.org/entity/Q1985786" then
item.calendarmodel = "julian"
item.jul_date = moduleDates.parseISO8601DateTime(snak.datavalue.value.time)
item.time = moduleDates.JulianDateToUNIXTime(item.jul_date)
if item.time == nil then
item.structure = nil
else
item.structure = os.date("*t", item.time)
end
else
if snak.datavalue.value.calendarmodel == "http://www.wikidata.org/entity/Q1985727" then
item.calendarmodel = "gregorian"
else
item.calendarmodel = "unknown"
end
item.structure = moduleDates.parseISO8601DateTime(snak.datavalue.value.time)
item.time = tonumber(os.time(item.structure))
item.jul_date = nil
end
elseif snak.snaktype == "somevalue" then
item = { unknown = "unknown" }
end
if item ~= nil then
if value.rank == "preferred" then
table.insert(preferred_values, item)
elseif value.rank == "normal" then
table.insert(normal_values, item)
end
end
end
if #preferred_values > 0 then
return preferred_values
elseif #normal_values > 0 then
return normal_values
else
return nil
end
end
--[[
Процедура для тестирования parseProperty()
{{#invoke:Wikidata/Даты|test_parseProperty|P569}}
{{#invoke:Wikidata/Даты|test_parseProperty|P570}}
]]
function p.test_parseProperty(frame)
local result = p.parseProperty(tostring(frame.args[1]))
local s_result = ""
for key, value in pairs(result) do
s_result = s_result .. "value = ".. os.date("%d.%m.%Y", value.time) .. " year = " .. tostring(value.structure.year) .. " month = " .. tostring(value.structure.month) .. " day = " .. tostring(value.structure.day) .. " " .. value.calendarmodel .. " (" .. tostring(value.time) .. ")\n\n"
end
return s_result
end
function formatDate( value, infoclass, categoryPrefix, unknownCategory)
local s_result
if value.unknown then
s_result = "''неизвестно''"
if ( unknownCategory ) then
s_result = s_result .. "[[" .. unknownCategory.. "]]"
end
elseif value.precision == 7 then -- century precision
if value.structure.year < 0 then
s_result = moduleMath.rn(math.floor(-value.structure.year/100)) .. ' век до н. э.'
else
s_result = moduleMath.rn(math.floor(value.structure.year/100)) .. ' век'
end
elseif value.precision == 8 then -- 10-year precision
if value.structure.year < 0 then
local s_year = tostring(-value.structure.year)
s_result = '[[:w:' .. s_year .. '-е годы до н. э.|' .. s_year .. '-е до н. э.]]'
else
local s_year = tostring(value.structure.year)
s_result = '[[:w:' .. s_year .. '-е годы|' .. s_year .. '-е]]'
end
elseif value.precision == 9 then -- year precision
if value.structure.year < 0 then
local s_year = tostring(-value.structure.year)
s_result = '[[:w:' .. s_year .. ' год до н. э.|' .. s_year .. ' до н. э.]]'
else
local s_year = tostring(value.structure.year)
s_result = '[[:w:' .. s_year .. ' год|' .. s_year .. ']]'
end
elseif value.precision == 10 then -- month precision
if value.structure.year < 0 then
local s_year = tostring(-value.structure.year)
s_result = moduleDates.getMonthNom(value.structure.month) .. ' [[:w:' .. s_year .. ' год до н. э.|' .. s_year .. ' до н. э.]]'
else
local s_year = tostring(value.structure.year)
s_result = moduleDates.getMonthNom(value.structure.month) .. ' [[:w:' .. s_year .. ' год|' .. s_year .. ']]'
end
elseif value.jul_date == nil then
return moduleDates.formatWikiImpl(value.structure, value.structure, infocardClass, categoryPrefix)
elseif value.structure == nil then -- Даты до ввода грегорианского календаря
return moduleDates.formatWikiImpl(value.jul_date, value.jul_date, infocardClass, categoryPrefix)
else
return moduleDates.formatWikiImpl(value.jul_date, value.structure, infocardClass, categoryPrefix)
end
return s_result
end
-- accepts table of time+precision values
function ageCurrent ( bTable )
local possibleAge = "NYA" -- it meansm "Not Yet Assigned", not what you imagined!
for bKey, bValue in pairs(bTable) do
if ( bValue.unknown ) then
return nil
end
local bStructure = bValue.structure
local bPrecision = bValue.precision
local dStructure = os.date( "*t" )
local calculatedAge = ageImpl ( bStructure, bPrecision, dStructure, 11 )
if ( possibleAge == "NYA" ) then
possibleAge = calculatedAge
else
if ( possibleAge ~= calculatedAge ) then
possibleAge = nil
end
end
end
return possibleAge
end
-- accepts tables of time+precision values
function age ( bTable, dTable )
local possibleAge = "NYA" -- it meansm "Not Yet Assigned", not what you imagined!
for bKey, bValue in pairs( bTable ) do
if ( bValue.unknown ) then
return nil
end
local bStructure = bValue.structure
local bPrecision = bValue.precision
for dKey, dValue in pairs( dTable ) do
if ( dValue.unknown ) then
return nil
end
local dStructure = dValue.structure
local dPrecision = dValue.precision
local calculatedAge = ageImpl ( bStructure, bPrecision, dStructure, dPrecision )
if ( possibleAge == "NYA" ) then
possibleAge = calculatedAge
else
if ( possibleAge ~= calculatedAge ) then
possibleAge = nil
end
end
end
end
return possibleAge
end
function ageImpl ( bStructure, bPrecision, dStructure, dPrecision )
if ( not bStructure or not dStructure or bPrecision < 10 or dPrecision < 10 ) then
return nil
end
if ( bPrecision == 10 or dPrecision == 10 ) then
if ( bStructure.month < dStructure.month ) then
return dStructure.year - bStructure.year
end
if ( bStructure.month == dStructure.month ) then
return nil
end
if ( bStructure.month > dStructure.month ) then
return dStructure.year - bStructure.year - 1
end
end
if ( bStructure.month < dStructure.month ) then
return dStructure.year - bStructure.year
end
if ( bStructure.month == dStructure.month ) then
if ( bStructure.day <= dStructure.day ) then
return dStructure.year - bStructure.year
else
return dStructure.year - bStructure.year - 1
end
end
if ( bStructure.month > dStructure.month ) then
return dStructure.year - bStructure.year - 1
end
return nil
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
--[[
Вызывается из Шаблон:Обавторе, если не задан параметр ДАТАРОЖДЕНИЯ
{{#invoke:Wikidata/Даты|dateOfBirth}}
]]
function p.dateOfBirth()
local appendToCategory = false
local bTable = p.parseProperty ( "p569" )
if not bTable then
return ''
end
local dTable = p.parseProperty ( "p570" )
checkDupDates(bTable);
local result = ''
for key, value in pairs(bTable) do
if result ~= '' then
result = result .. ' или '
end
if ( appendToCategory ) then
result = result .. formatDate(value, 'bday', 'Родившиеся ', 'К:Персоналии, чья дата рождения не установлена')
else
result = result .. formatDate(value, 'bday', nil, nil )
end
end
if ( not dTable ) then
local age = ageCurrent( bTable )
if ( age ) then
result = result .. ' <span style="white-space:nowrap;">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'лет', 'года') .. ')</span>'
if ( age > 150 and appendToCategory ) then
result = result .. '[[К:Википедия:Статьи о персоналиях с большим текущим возрастом]]'
end
end
end
return result
end
--[[
Вызывается из Шаблон:Обавторе, если не задан параметр ДАТАСМЕРТИ
{{#invoke:Wikidata/Даты|dateOfDeath}}
]]
function p.dateOfDeath()
local appendToCategory = false
local dTable = p.parseProperty ( "p570" )
if not dTable then
return ''
end
local bTable = p.parseProperty ( "p569" )
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
if ( bTable and dTable ) then
local age = age( bTable, dTable )
if ( age ) then
result = result .. ' <span style="white-space:nowrap;">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'лет', 'года') .. ')</span>'
if ( age > 150 and appendToCategory ) then
result = result .. '[[К:Википедия:Статьи о персоналиях с большим возрастом во время смерти]]'
end
end
end
return result
end
return p