Редактирование:
Модуль:Wikidata/date
Перейти к навигации
Перейти к поиску
Внимание:
Вы не вошли в систему. Ваш IP-адрес будет общедоступен, если вы запишете какие-либо изменения. Если вы
войдёте
или
создадите учётную запись
, её имя будет использоваться вместо IP-адреса, наряду с другими преимуществами.
Анти-спам проверка.
Не
заполняйте это!
--settings local nowLabel = 'наст. время' local moduleDates = require( "Module:Dates" ) local moduleWikidata = require( "Module:Wikidata" ) local dateCat = require("Module:Infocards/dateCat") -- FIXME: undeclared global variable, used 3 times local infoclass local 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 local function ageImpl ( bStructure, bPrecision, dStructure, dPrecision ) if ( not bStructure or not dStructure or bPrecision < 10 or dPrecision < 10 ) then return nil end local shift = 0 if ( bStructure.year < 0 and dStructure.year > 0 ) then shift = -1 end if ( bPrecision == 10 or dPrecision == 10 ) then if ( bStructure.month < dStructure.month ) then return dStructure.year - bStructure.year + shift end if ( bStructure.month == dStructure.month ) then return nil end if ( bStructure.month > dStructure.month ) then return dStructure.year - bStructure.year - 1 + shift end end if ( bStructure.month < dStructure.month ) then return dStructure.year - bStructure.year + shift end if ( bStructure.month == dStructure.month ) then if ( bStructure.day <= dStructure.day ) then return dStructure.year - bStructure.year + shift else return dStructure.year - bStructure.year - 1 + shift end end if ( bStructure.month > dStructure.month ) then return dStructure.year - bStructure.year - 1 + shift end return nil end -- accepts table of time+precision values local function ageCurrent ( bTable ) local possibleAge = "NYA" -- it means "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 local function age ( bTable, dTable ) local possibleAge = "NYA" -- it means "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 if ( bValue.calendar == 'julian' and dValue.calendar == 'gregorian' ) then -- to calculate age, need to adjust bStructure to gregorian calendar local shift = math.floor(bStructure.year/100-2) - math.floor(bStructure.year/400) -- TODO: re-implement this properly bStructure.day = bStructure.day + shift end 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 local 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 local 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 local 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 local 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) if not Y or not M or not D or not h or not m or not s or not oh or not om then return nil end return tonumber(os.time({year=Y, month=M, day=D, hour=(h+oh), min=(m+om), sec=s})) end local function parseClaim ( claim ) if ( claim.mainsnak.snaktype == "value" ) then local timeISO8601 = string.gsub( string.gsub( tostring( claim.mainsnak.datavalue.value.time ), '-00%-', '-01-' ), '-00T', '-01T' ) local unixtime = parseISO8601( timeISO8601 ) local structure = os.date("*t", unixtime) local precision = tonumber( claim.mainsnak.datavalue.value.precision ) local calendarmodel = 'gregorian' if (mw.ustring.find(claim.mainsnak.datavalue.value.calendarmodel, 'Q1985786', 1, true)) then calendarmodel = 'julian' end local item = { structure=structure, precision=precision, calendar = calendarmodel } return item elseif ( claim.mainsnak.snaktype == "novalue" ) then -- novalue return { unknown="novalue" } else --unknown return { unknown="unknown" } end end -- returns table of time+precision values for specified property local function parseProperty ( context, options, propertyId ) if ( not context ) then error( 'context not specified'); end if ( not options ) then error( 'options not specified'); end if ( not options.entity ) then error( 'options.entity is missing'); end if ( not propertyId ) then error( 'propertyId not specified'); end local claims = context.selectClaims( options, propertyId ) if not claims then return nil end local result = {} for key, claim in pairs( claims ) do table.insert ( result, parseClaim( claim ) ) end return result end -- проверка на совпадающие даты с разной моделью календаря local 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 -- returns first qualifier of specified propertyId local function getQualifierWithDataValue( statement, qualifierPropertyId ) if ( statement.qualifiers and statement.qualifiers[qualifierPropertyId] ) then local qualifiers = statement.qualifiers[qualifierPropertyId] for _, qualifier in ipairs( qualifiers ) do if (qualifier.datavalue) then return qualifier end end end return nil end local p = {} local function formatDecade( time, categoryNamePrefix ) local bce = '' local year if time.year < 0 then bce = ' до н. э.' year = math.floor( math.abs( time.year ) / 10 ) * 10 else year = math.floor( time.year / 10 ) * 10 end local unit = '-е' if isGenitive then unit = '-х' end local value = '' .. year .. unit .. bce if categoryNamePrefix then return value .. '[[Category:' .. categoryNamePrefix .. ' в ' .. year .. '-е годы' .. bce .. ']]' end return value end local function formatCentury( time, categoryNamePrefix, isGenitive ) local moduleRoman = require( 'Module:RomanNumber' ) local bce = '' local century if time.year < 0 then bce = ' до н. э.' century = math.floor( ( math.abs( time.year ) - 1 ) / 100 ) + 1 else century = math.floor( ( time.year - 1 ) / 100 ) + 1 end local unit = 'век' if isGenitive then unit = 'века' end local infix = ' в ' if century == 2 then infix = ' во ' end if moduleRoman then century = moduleRoman.toRomanNumber( century ) end local value = '[[' .. century .. ' век' .. bce .. '|' .. century .. ' ' .. unit .. bce .. ']]' if categoryNamePrefix then return value .. '[[Category:' .. categoryNamePrefix .. infix .. century .. ' веке' .. bce .. ']]' end return value end local function formatMillenium( time, categoryNamePrefix, isGenitive ) local bce = '' local millenium if time.year < 0 then bce = ' до н. э.' millenium = math.floor( ( math.abs( time.year ) - 1 ) / 1000 ) + 1 else millenium = math.floor( ( time.year - 1 ) / 1000 ) + 1 end local unit = '-е тысячелетие' if isGenitive then unit = '-го тысячелетия' end local value = '[[' .. millenium .. '-е тысячелетие' .. bce .. '|' .. millenium .. unit .. bce .. ']]' if categoryNamePrefix then local infix = ' в ' if millenium == 2 then infix = ' во ' end return value .. '[[Category:' .. categoryNamePrefix .. infix .. millenium .. '-м тысячелетии' .. bce .. ']]' else return value end end local function formatDateImpl( value, options, microformatClass, categoryPrefix, leftBracket, rightBracket, nolinks, isGenitive ) if ( not value ) then error( 'value not specified'); end if ( not options ) then error( 'options not specified'); end -- The calendar model used for saving the data is always the proleptic Gregorian calendar according to ISO 8601. local timeISO8601 = string.gsub( string.gsub( tostring( value.time ), '-00%-', '-01-' ), '-00T', '-01T' ) local unixtime = parseISO8601( timeISO8601 ) if not unixtime then return '' end local structure = os.date("*t", unixtime) local precision = tonumber( value.precision ) if precision <= 6 then return formatMillenium( structure, categoryPrefix, isGenitive ) end if precision == 7 then return formatCentury( structure, categoryPrefix, isGenitive ) end if precision == 8 then return formatDecade( structure, categoryPrefix, isGenitive ) end if precision == 9 then local tCopy = deepcopy( structure ) tCopy.day = nil tCopy.month = nil return moduleDates.formatWikiImpl( tCopy, tCopy, infoclass, categoryPrefix, leftBracket, rightBracket, nolinks ) end -- year and month only if precision == 10 then local tCopy = deepcopy( structure ) tCopy.day = nil return moduleDates.formatWikiImpl( tCopy, tCopy, infoclass, categoryPrefix, leftBracket, rightBracket, nolinks ) end local calendarmodel = 'gregorian' if (mw.ustring.find(value.calendarmodel, 'Q1985786', 1, true)) then calendarmodel = 'julian' end if (calendarmodel == 'gregorian') then return moduleDates.formatWikiImpl( structure, structure, microformatClass, categoryPrefix, leftBracket, rightBracket, nolinks ) else return p.formatAsJulian( timeISO8601, infoclass, categoryPrefix, leftBracket, rightBracket, nolinks ) end end local function formatApproximateDateClaim( context, options, statement, unknownDateCategory ) if ( not context ) then error( 'context not specified'); end if ( not options ) then error( 'options not specified'); end if ( not options.entity ) then error( 'options.entity is missing'); end if ( not statement ) then error( 'statement not specified'); end if options.nocat then unknownDateCategory = "" end local qNotSoonerThan = getQualifierWithDataValue( statement, 'P1319' ) local qNotLaterThan = getQualifierWithDataValue( statement, 'P1326' ) if ( qNotSoonerThan or qNotLaterThan ) then local results = {} if ( qNotSoonerThan ) then local formattedDate = formatDateImpl( qNotSoonerThan.datavalue.value, {}, nil, nil, options.leftBracket, options.rightBracket, options.nolinks, true ) local value = 'не ранее ' .. context.wrapSnak( formattedDate, qNotSoonerThan.hash ) table.insert( results, context.wrapQualifier( value, 'P1319' ) ) end if ( qNotLaterThan ) then local formattedDate = formatDateImpl( qNotLaterThan.datavalue.value, {}, nil, nil, options.leftBracket, options.rightBracket, options.nolinks, true ) local value = 'не позднее ' .. context.wrapSnak( formattedDate, qNotLaterThan.hash ) table.insert( results, context.wrapQualifier( value, 'P1326' ) ) end return mw.text.listToText( results, ' и ' , ' и ' ) .. unknownDateCategory .. context.formatRefs( options, statement ) end return nil end function p.formatDateOfBirthClaim( context, options, statement ) local value = formatApproximateDateClaim( context, options, statement, dateCat.categoryUnknownBirthDate ) if value then return value end options['conjunction'] = ' или ' options['value-module'] = 'Wikidata/date' options['value-function'] = 'formatBirthDate' options.i18n.somevalue = '\'\'неизвестно\'\'' .. dateCat.categoryUnknownBirthDate local circumstances = context.getSourcingCircumstances( statement ) for _, itemId in ipairs( circumstances ) do if itemId == 'Q5727902' then options.isGenitive = true break end end local result = context.formatStatementDefault( context, options, statement ) local bTable = { parseClaim( statement ) } local dTable = parseProperty ( context, options, 'P570' ) if ( bTable and not dTable ) then local age = ageCurrent( bTable ) if ( age ) then if ( options.suppressAge == nil or options.suppressAge == '' ) then result = result .. ' <span style="white-space:nowrap;">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')</span>' end if ( not options.nocat ) then if ( age > 115 ) then result = result .. dateCat.categoryBigCurrentAge elseif (age >= 0) then result = result .. dateCat.categoryBiographiesOfLivingPersons else result = result .. dateCat.categoryNegativeAge end end end end return result end function p.formatDateOfDeathClaim( context, options, statement ) local value = formatApproximateDateClaim( context, options, statement, dateCat.categoryUnknownDeathDate ) if value then return value end options['conjunction'] = ' или ' options['value-module'] = 'Wikidata/date' options['value-function'] = 'formatDeathDate' options.i18n.somevalue = '\'\'неизвестно\'\'' .. dateCat.categoryUnknownDeathDate local circumstances = context.getSourcingCircumstances( statement ) for _, itemId in ipairs( circumstances ) do if itemId == 'Q5727902' then options.isGenitive = true break end end local result = context.formatStatementDefault( context, options, statement ) local bTable = parseProperty ( context, options, 'P569' ) local dTable = { parseClaim( statement ) } if ( bTable and dTable ) then local age = age( bTable, dTable ) if ( age ) then if ( options.suppressAge == nil or options.suppressAge == '' ) then result = result .. ' <span style="white-space:nowrap;">(' .. age .. ' ' .. mw.language.new( 'ru' ):plural( age, 'год', 'года', 'лет') .. ')</span>' end if ( not options.nocat and age < 0) then result = result .. dateCat.categoryNegativeAge end end -- returns category to recently deceased persons local unixAvailable, unixDateOfDeath = pcall(function() local r = os.time(dTable[1].structure) if ( r ~= os.time() ) then return r end error() end) if ( unixAvailable and os.time() - unixDateOfDeath < 31536000 and not options.nocat ) then result = result .. dateCat.categoryRecentlyDeceased end end return result end -- Reentry point for Wikidata Snak formatting function p.formatBirthDate( context, options, value ) if ( not context ) then error( 'context not specified'); end if ( not options ) then error( 'options not specified'); end if ( not value ) then error( 'value not specified'); end local microformatClass = nil if options.microformat ~= '-' then microformatClass = options.microformat or 'bday' end if ( options.nocat ) then return formatDateImpl( value, options, microformatClass, nil, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive ) else return formatDateImpl( value, options, microformatClass, 'Родившиеся', options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive ) end end -- Reentry point for Wikidata Snak formatting function p.formatDeathDate( context, options, value ) if ( not context ) then error( 'context not specified'); end if ( not options ) then error( 'options not specified'); end if ( not value ) then error( 'value not specified'); end local microformatClass = nil if options.microformat ~= '-' then microformatClass = options.microformat or 'dday' end if ( options.nocat and options.nocat ~= '' ) then return formatDateImpl( value, options, microformatClass, nil, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive ) else return formatDateImpl( value, options, microformatClass, 'Умершие', options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive ) end end -- Reentry point for Wikidata Snak formatting -- default one function p.formatDate( context, options, value ) if ( not context ) then error( 'context not specified'); end if ( not options ) then error( 'options not specified'); end if ( not value ) then error( 'value not specified'); end local microformatClass = options.microformat or nil if ( options.nocat and options.nocat ~= '' ) then return formatDateImpl( value, options, microformatClass, nil, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive ) else local categoryPrefix = options.categoryPrefix or nil return formatDateImpl( value, options, microformatClass, categoryPrefix, options.leftBracket, options.rightBracket, options.nolinks, options.isGenitive ) end end function p.formatDateIntervalProperty( context, options ) if ( not context ) then error( 'context not specified' ); end if ( not options ) then error( 'options not specified' ); end if ( not options.entity ) then error( 'options.entity missing' ); end -- Получение нужных утверждений local WDS = require( 'Module:WikidataSelectors' ) local fromProperty = options.property if options.from and options.from ~= '' then fromProperty = options.from end local fromClaims = WDS.load( options.entityId, fromProperty ) local toClaims = WDS.load( options.entityId, options.to ) if fromClaims == nil and toClaims == nil then return '' end local formattedFromClaims = {} if fromClaims then for i, claim in ipairs( fromClaims ) do local formattedStatement = context.formatStatement( options, claim ) if formattedStatement then formattedStatement = '<span class="wikidata-claim" data-wikidata-property-id="' .. string.upper( options.property ) .. '" data-wikidata-claim-id="' .. claim.id .. '">' .. formattedStatement .. '</span>' table.insert( formattedFromClaims, formattedStatement ) end end end local formattedToClaims = {} local toOptions = deepcopy( options ) toOptions.property = options.to toOptions.novalue = nowLabel if toClaims then for i, claim in ipairs( toClaims ) do local formattedStatement = context.formatStatement( toOptions, claim ) if formattedStatement then formattedStatement = '<span class="wikidata-claim" data-wikidata-property-id="' .. string.upper( toOptions.property ) .. '" data-wikidata-claim-id="' .. claim.id .. '">' .. formattedStatement .. '</span>' table.insert( formattedToClaims, formattedStatement ) end end end local out = '' local fromOut = mw.text.listToText( formattedFromClaims, options.separator, options.conjunction ) local toOut = mw.text.listToText( formattedToClaims, options.separator, options.conjunction ) if fromOut ~= '' or toOut ~= '' then if fromOut ~= '' then out = fromOut else out = '?' end if toOut ~= '' then out = out .. ' — ' .. toOut else local withinClaims = nil if options.within then WDS.load( options.entityId, options.within ) end if withinClaims == nil then out = 'с ' .. out else out = out .. ' — ' .. nowLabel end end end if out ~= '' then if options.before then out = options.before .. out end if options.after then out = out .. options.after end end return out end local lowestBoundary = '1582-10-05T00:00:00Z' local lastBoundary = '1918-01-31T00:00:00Z' local boundaries = { -- from (G) till next will be diff(G = J + diff), at current { lowestBoundary, 10 }, { '1700-02-29T00:00:00Z', 11 }, { '1800-02-29T00:00:00Z', 12 }, { '1900-02-29T00:00:00Z', 13 }, { lastBoundary, '' }, } -- Передаваемое время обязано быть по Юлианскому календарю (старому стилю) function p.formatAsJulian( julTimeISO8601, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks ) if 'table' == type( julTimeISO8601 ) then if julTimeISO8601.args and julTimeISO8601.args[1] then julTimeISO8601 = julTimeISO8601.args[1] else return 'unknown argument type: ' .. type( julTime ) .. ': ' .. table.tostring( julTime ) end end julTimeISO8601 = mw.text.trim( julTimeISO8601 ) julTimeISO8601 = string.gsub( julTimeISO8601, '^+', '' ) local julTime = parseISO8601( julTimeISO8601 ) local t = os.date( "*t", julTime ) if ( julTime < parseISO8601( lowestBoundary ) ) then -- 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 if ( julTimeISO8601 >= lastBoundary ) then return "''некорректная дата (юлианский календарь не используется после 1918-01-26)''" end -- julian and grigorian for i = 1, #boundaries, 1 do local b1 = boundaries[i][1] local b2 = boundaries[i + 1][1] if ( b1 <= julTimeISO8601 and julTimeISO8601 < b2 ) then local diff = boundaries[i][2] if string.sub( julTimeISO8601, 1, 10 ) == string.sub( boundaries[i][1], 1, 10 ) then t = { year = t.year, month = 2, day = 29 } diff = diff - 1 end local gregTime = os.date( "*t", julTime + diff * 24 * 60 * 60 ) return moduleDates.formatWikiImpl( t, gregTime, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks ) end end return "''ошибка в модуле Модуль:Wikidata/date''" end return p
Описание изменений:
Пожалуйста, учтите, что любой ваш вклад в проект «Валленланд Вики» может быть отредактирован или удалён другими участниками. Если вы не хотите, чтобы кто-либо изменял ваши тексты, не помещайте их сюда.
Вы также подтверждаете, что являетесь автором вносимых дополнений, или скопировали их из источника, допускающего свободное распространение и изменение своего содержимого (см.
Валленланд Вики:Авторские права
).
НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ МАТЕРИАЛЫ!
Отменить
Справка по редактированию
(в новом окне)
Шаблон, используемый на этой странице:
Модуль:Wikidata/date/doc
(
править
)
Навигация
Персональные инструменты
Вы не представились системе
Обсуждение
Тёмная тема
Вклад
Создать учётную запись
Войти
Пространства имён
Модуль
Обсуждение
English
Просмотры
Читать
Править код
История
Ещё
Поиск
Навигация
Заглавная страница
Свежие правки
Случайная страница
Справка по MediaWiki
Инструменты
Ссылки сюда
Связанные правки
Служебные страницы
Сведения о странице
Получить короткий URL