«Модуль:Wikidata/date» и «Модуль:Wikidata/date/песочница»: разница между страницами
(Различия между страницами)
Karaby (обсуждение | вклад) м 1 версия импортирована |
Karaby (обсуждение | вклад) м 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") | ||
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. | local fromClaims = WDS.filter( options.entity.claims, fromProperty ) | ||
local toClaims = WDS. | 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 | ||
if withinClaims ~= nil then | |||
if withinClaims | |||
out = 'с ' .. out | out = 'с ' .. out | ||
else | else | ||
| Строка 649: | Строка 654: | ||
return out | return out | ||
end | end | ||
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, | { '-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 }, | ||
{ | { '-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( | local mainBoundary = parseISO8601('1582-10-05T00:00:00Z') -- any dates before 1582 should be only julian | ||
if 'table' == type( | local lastBoundary = parseISO8601('1918-01-31T00:00:00Z') -- any dates after 1918 should be gregorian even if in Russia | ||
-- Функция принимает первым параметром 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 | ||
stringJulTime = mw.text.trim(stringJulTime) | |||
local t = os.date( "*t", julTime ) | local t = os.date( "*t", julTime ) | ||
if ( julTime <= lowestBoundary ) then | |||
if ( julTime < | return "''некорректная дата (недостижимая точность)''" | ||
end | end | ||
if ( | if ( julTime >= lastBoundary ) then | ||
return "''некорректная дата (юлианский | return "''некорректная дата (юлианский не используется после 1918-01-26)''" | ||
end | end | ||
for i=1,#boundaries,1 do | |||
for i = 1, #boundaries, 1 do | local b1 = boundaries[i][2] | ||
local b1 = boundaries[i][ | local b2 = boundaries[i + 1][2] | ||
local b2 = boundaries[i + 1][ | if ( b1 <= julTime and julTime < b2 ) then | ||
if ( b1 <= | -- local b1s = os.date( "*t", b1 ) | ||
-- if ( b1s.year == t.year and b1s.month == t.month and b1s.day == t.day) then | |||
if | if (mw.text.truncate(stringJulTime, 10) == mw.text.truncate(boundaries[i][1], 10)) then | ||
t | -- if (stringJulTime == boundaries[i][1]) then -- wrong as works only for 00:00, will update later | ||
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 | ||
end | end | ||
end | end | ||
return "''ошибка в модуле Модуль:Wikidata/date''" | if ( julTime >= lastBoundary ) then | ||
return "''ошибка в модуле Модуль:Wikidata/date (не найден сдвиг конвертации календаря)''" | |||
end | |||
end | end | ||
return p | return p | ||