«Модуль:Wikidata/date» и «Модуль:Wikidata/date/песочница»: разница между страницами

(Различия между страницами)
Перейти к навигации Перейти к поиску
Первая страница
Вторая страница
м 1 версия импортирована
 
м 1 версия импортирована
 
Строка 5: Строка 5:
local moduleWikidata = require( "Module:Wikidata" )
local moduleWikidata = require( "Module:Wikidata" )
local dateCat = require("Module:Infocards/dateCat")
local dateCat = require("Module:Infocards/dateCat")
-- FIXME: undeclared global variable, used 3 times
local infoclass


local function deepcopy(orig)
local function deepcopy(orig)
Строка 63: Строка 60:
end
end


-- accepts table of time+precision values
-- accepts table of time+precision values for dates of birth
-- for each element computes age at current time using function ageImpl
local function ageCurrent ( bTable )
local function ageCurrent ( bTable )
local possibleAge = "NYA" -- it means "Not Yet Assigned", not what you imagined!
local possibleAge = "NYA" -- it means "Not Yet Assigned", not what you imagined!
Строка 89: Строка 87:
end
end


-- accepts tables of time+precision values
-- accepts tables of time+precision values for dates of birth and death
-- returns age if it is well-defined and if all the dates in the original tables agree with each other
local function age ( bTable, dTable )
local function age ( bTable, dTable )
local possibleAge = "NYA" -- it means "Not Yet Assigned", not what you imagined!
local possibleAge = "NYA" -- it means "Not Yet Assigned", not what you imagined!
Строка 117: Строка 116:
possibleAge = calculatedAge
possibleAge = calculatedAge
else
else
if ( possibleAge ~= calculatedAge ) then
if ( possibleAge ~= calculatedAge ) then  
possibleAge = nil
possibleAge = nil -- if we already computed another age for the same person, it looks like the input data is incorrect
end
end
end
end
Строка 150: Строка 149:
end
end


-- transforms string in format '1900-02-29T00:00:00Z' to one number (seconds from standard epoch, may be negative before 1970)
local function parseISO8601(str)
local function parseISO8601(str)
if 'table' == type(str) then
if 'table' == type(str) then
Строка 170: Строка 170:
end
end


-- parses string claim.mainsnak.datavalue.value.time into a structure
-- if it is julian parses it as if it were gregorian (!) but leaves a flag calendarmodel = 'julian' that may be used later
local function parseClaim ( claim )
local function parseClaim ( claim )
if ( claim.mainsnak.snaktype == "value" ) then
if ( claim.mainsnak.snaktype == "value" ) then
-- The calendar model used for saving the data is always the proleptic Gregorian calendar according to ISO 8601.
-- However wikidata uses sometimes julian, see Q1985786
local timeISO8601 = string.gsub( string.gsub( tostring( claim.mainsnak.datavalue.value.time ), '-00%-', '-01-' ), '-00T', '-01T' )
local timeISO8601 = string.gsub( string.gsub( tostring( claim.mainsnak.datavalue.value.time ), '-00%-', '-01-' ), '-00T', '-01T' )
local unixtime = parseISO8601( timeISO8601 )
local unixtime = parseISO8601( timeISO8601 )
Строка 211: Строка 215:


-- проверка на совпадающие даты с разной моделью календаря
-- проверка на совпадающие даты с разной моделью календаря
-- принимает массив дат, вырезает из него совпадающие (ничего не возвращает, изменяет поданный объект);
-- если одна дата записана и как gregorian, и как julian, удаляет gregorian версию
local function checkDupDates( t )
local function checkDupDates( t )
if #t > 1 then
if #t > 1 then
Строка 350: Строка 356:


-- The calendar model used for saving the data is always the proleptic Gregorian calendar according to ISO 8601.
-- The calendar model used for saving the data is always the proleptic Gregorian calendar according to ISO 8601.
-- However in wikidata Q1985786 may store 'julian' which will mean proleptic Julilan calendar
-- We parse the date as if it were gregorian and then if julian apply fixes
local timeISO8601 = string.gsub( string.gsub( tostring( value.time ), '-00%-', '-01-' ), '-00T', '-01T' )
local timeISO8601 = string.gsub( string.gsub( tostring( value.time ), '-00%-', '-01-' ), '-00T', '-01T' )
local unixtime = parseISO8601( timeISO8601 )
local unixtime = parseISO8601( timeISO8601 )
Строка 580: Строка 588:
fromProperty = options.from
fromProperty = options.from
end
end
local fromClaims = WDS.load( options.entityId, fromProperty )
local fromClaims = WDS.filter( options.entity.claims, fromProperty )
local toClaims = WDS.load( options.entityId, options.to )
local toClaims = WDS.filter( options.entity.claims, options.to )
local withinClaims = WDS.filter( options.entity.claims, options.within )


if fromClaims == nil and toClaims == nil then
if fromClaims == nil and toClaims == nil then
Строка 615: Строка 624:
local fromOut = mw.text.listToText( formattedFromClaims, options.separator, options.conjunction )
local fromOut = mw.text.listToText( formattedFromClaims, options.separator, options.conjunction )
local toOut = mw.text.listToText( formattedToClaims, options.separator, options.conjunction )
local toOut = mw.text.listToText( formattedToClaims, options.separator, options.conjunction )
 
if fromOut ~= '' or toOut ~= '' then
if fromOut ~= '' or toOut ~= '' then
if fromOut ~= '' then
if fromOut ~= '' then
Строка 626: Строка 635:
out = out .. ' — ' .. toOut
out = out .. ' — ' .. toOut
else
else
local withinClaims = nil
if withinClaims ~= nil then
if options.within then
WDS.load( options.entityId, options.within )
end
if withinClaims == nil then
out = 'с ' .. out
out = 'с ' .. out
else
else
Строка 649: Строка 654:
return out
return out
end
end
local lowestBoundary = '1582-10-05T00:00:00Z'
local lastBoundary = '1926-01-01T00:00:00Z' -- Turkey


local boundaries = {
local boundaries = {
-- from (G) till next will be diff(G = J + diff), at current
-- from (G) till next will be diff(G = J + diff), at current
{ lowestBoundary,         10 },
{ '-900-02-20T00:00:00Z', parseISO8601('-900-02-20T00:00:00Z'), -9 }, -- same as lowestBoundary
{ '1700-02-29T00:00:00Z', 11 },
{ '-700-02-29T00:00:00Z', parseISO8601('-700-02-29T00:00:00Z'), -8 },
{ '1800-02-29T00:00:00Z', 12 },
{ '-600-02-29T00:00:00Z', parseISO8601('-600-02-29T00:00:00Z'), -7 },
{ '1900-02-29T00:00:00Z', 13 },
{ '-500-02-29T00:00:00Z', parseISO8601('-500-02-29T00:00:00Z'), -6 },
{ lastBoundary, '' },
{ '-300-02-29T00:00:00Z', parseISO8601('-300-02-29T00:00:00Z'), -5 },
{ '-200-02-29T00:00:00Z', parseISO8601('-200-02-29T00:00:00Z'), -4 },
{ '-100-02-29T00:00:00Z', parseISO8601('-100-02-29T00:00:00Z'), -3 },
{ '0000-00-00T00:00:00Z', parseISO8601('0000-00-00T00:00:00Z'), -2 },
{ '0100-02-29T00:00:00Z', parseISO8601('0100-02-29T00:00:00Z'), -1 },
{ '0200-02-29T00:00:00Z', parseISO8601('0200-02-29T00:00:00Z'),  0 },
{ '0300-02-29T00:00:00Z', parseISO8601('0300-02-29T00:00:00Z'),  1 },
{ '0500-02-29T00:00:00Z', parseISO8601('0500-02-29T00:00:00Z'),  2 },
{ '0600-02-29T00:00:00Z', parseISO8601('0600-02-29T00:00:00Z'),  3 },
{ '0700-02-29T00:00:00Z', parseISO8601('0700-02-29T00:00:00Z'),  4 },
{ '0900-02-29T00:00:00Z', parseISO8601('0900-02-29T00:00:00Z'),  5 },
{ '1000-02-29T00:00:00Z', parseISO8601('1000-02-29T00:00:00Z'),  6 },
{ '1100-02-29T00:00:00Z', parseISO8601('1100-02-29T00:00:00Z'),  7 },
{ '1300-02-29T00:00:00Z', parseISO8601('1300-02-29T00:00:00Z'),  8 },
{ '1400-02-29T00:00:00Z', parseISO8601('1400-02-29T00:00:00Z'),  9 },
{ '1500-02-29T00:00:00Z', parseISO8601('1500-02-29T00:00:00Z'), 10 },
{ '1700-02-29T00:00:00Z', parseISO8601('1700-02-29T00:00:00Z'), 11 },
{ '1800-02-29T00:00:00Z', parseISO8601('1800-02-29T00:00:00Z'), 12 },
{ '1900-02-29T00:00:00Z', parseISO8601('1900-02-29T00:00:00Z'), 13 },
{ '1918-01-31T00:00:00Z', parseISO8601('1918-01-31T00:00:00Z'), '' }, -- same as lastBoundary
}
}


-- Передаваемое время обязано быть по Юлианскому календарю (старому стилю)
local lowestBoundary = parseISO8601('-900-02-20T00:00:00Z') -- we do not expect to know precise dates before 900 B.C.
function p.formatAsJulian( julTimeISO8601, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
local mainBoundary = parseISO8601('1582-10-05T00:00:00Z')  -- any dates before 1582 should be only julian
if 'table' == type( julTimeISO8601 ) then
local lastBoundary = parseISO8601('1918-01-31T00:00:00Z')  -- any dates after 1918 should be gregorian even if in Russia
if julTimeISO8601.args and julTimeISO8601.args[1] then
 
julTimeISO8601 = julTimeISO8601.args[1]
 
else
-- Функция принимает первым параметром julTime значение в секундах такое,
return 'unknown argument type: ' .. type( julTime ) .. ': ' .. table.tostring( julTime )
  -- что если по нему построить дату григорианского календаря, то получается верная дата юлианского календаря.
  -- Такое значение можно из даты в юлианском календаре получить функцией parseISO8601.
-- По такой дате вычисляются (обратно) дата в юлианском календаре и дата в григорианском календаре
  -- и выводится один или два в зависимости от того, в каком диапазоне лежит дата.
function p.formatAsJulian( stringJulTime, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
if 'string' == type(stringJulTime) then
julTime = parseISO8601( stringJulTime )
else
if 'table' == type( stringJulTime ) then
if stringJulTime.args and stringJulTime.args[1] then
stringJulTime = stringJulTime.args[1]
julTime = parseISO8601( stringJulTime )
else
return 'unknown argument type: ' .. type( stringJulTime ) .. ': ' .. table.tostring( stringJulTime )
end
end
end
end
end
 
julTimeISO8601 = mw.text.trim( julTimeISO8601 )
stringJulTime = mw.text.trim(stringJulTime)
julTimeISO8601 = string.gsub( julTimeISO8601, '^+', '' )
local julTime = parseISO8601( julTimeISO8601 )
local t = os.date( "*t", julTime )
local t = os.date( "*t", julTime )
 
if ( julTime <= lowestBoundary ) then
if ( julTime < parseISO8601( lowestBoundary ) ) then
return "''некорректная дата (недостижимая точность)''"
-- only julian
if string.find( julTimeISO8601, '-02-29T', 1, true ) then
t = { year = t.year, month = 2, day = 29 }
end
return moduleDates.formatWikiImpl( t, t, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
end
end
if ( julTimeISO8601 >= lastBoundary ) then
if ( julTime >= lastBoundary ) then
return "''некорректная дата (юлианский календарь не используется после 1926-01-01)''"
return "''некорректная дата (юлианский не используется после 1918-01-26)''"
end
end


-- julian and grigorian
for i=1,#boundaries,1 do
for i = 1, #boundaries, 1 do
local b1 = boundaries[i][2]
local b1 = boundaries[i][1]
local b2 = boundaries[i + 1][2]
local b2 = boundaries[i + 1][1]
if ( b1 <= julTime and julTime < b2 ) then
if ( b1 <= julTimeISO8601 and julTimeISO8601 < b2 ) then
-- local b1s = os.date( "*t", b1 )
local diff = boundaries[i][2]
-- if ( b1s.year == t.year and b1s.month == t.month and b1s.day == t.day) then
if string.sub( julTimeISO8601, 1, 10 ) == string.sub( boundaries[i][1], 1, 10 ) then
if (mw.text.truncate(stringJulTime, 10) == mw.text.truncate(boundaries[i][1], 10)) then
t = { year = t.year, month = 2, day = 29 }
-- if (stringJulTime == boundaries[i][1]) then -- wrong as works only for 00:00, will update later
diff = diff - 1
local gregTime = os.date( "*t", julTime + (boundaries[i][3]-1) * 24 * 60 * 60 )
return moduleDates.formatWikiImpl( {year=t.year, month=2, day=29}, gregTime , infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
else
if ( julTime < mainBoundary ) then
-- only julian
return moduleDates.formatWikiImpl( t, t, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
else
--julian and grigorian
local gregTime = os.date( "*t", julTime + boundaries[i][3] * 24 * 60 * 60 )
return moduleDates.formatWikiImpl( t, gregTime, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
end
end
end
local gregTime = os.date( "*t", julTime + diff * 24 * 60 * 60 )
return moduleDates.formatWikiImpl( t, gregTime, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
end
end
end
end


return "''ошибка в модуле Модуль:Wikidata/date''"
if ( julTime >= lastBoundary ) then
return "''ошибка в модуле Модуль:Wikidata/date (не найден сдвиг конвертации календаря)''"
end
end
end


return p
return p