Мазмұнға өту

Module:Wikidata/date

Уикипедия — ашық энциклопедиясынан алынған мәлімет

Бұл модульдің құжаттамасын Module:Wikidata/date/doc бетінде бастай аласыз

-- Қазақша локализация параметрлері
local nowLabel = 'қазіргі уақыт'

local moduleDates = require( "Module:Dates" )
--local moduleWikidata = require( "Module:Wikidata" )
local dateCat = require("Module:Infocards/dateCat")

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
		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

local function ageCurrent ( bTable )
	local possibleAge = "NYA" 

	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

local function age ( bTable, dTable )
	local possibleAge = "NYA"

	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
				local shift = math.floor(bStructure.year/100-2) - math.floor(bStructure.year/400)
				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 
	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 nil
		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
		return { structure=structure, precision=precision, calendar = calendarmodel }
	elseif ( claim.mainsnak.snaktype == "novalue" ) then
		return { unknown="novalue" }
	else
		return { unknown="unknown" }
	end
end

local function parseProperty ( context, options, propertyId )
	if ( not context ) then error( 'context 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 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 value = year .. '-ші жылдар' .. bce

	if categoryNamePrefix then
		local catAction = (categoryNamePrefix == 'birth' and 'туғандар') or 'қайтыс болғандар'
		return value .. '[[Category:' .. year .. ' жылдары ' .. catAction .. bce .. ']]'
	end
	return value
end

local function formatCentury( time, categoryNamePrefix )
	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
	
	if moduleRoman then century = moduleRoman.toRomanNumber( century ) end
	local value = '[[' .. century .. ' ғасыр' .. bce .. '|' .. century .. ' ғасыр' .. bce .. ']]'

	if categoryNamePrefix then
		local catAction = (categoryNamePrefix == 'birth' and 'туғандар') or 'қайтыс болғандар'
		return value .. '[[Category:' .. century .. ' ғасырда ' .. catAction .. bce .. ']]'
	end
	return value
end

local function formatMillenium( time, categoryNamePrefix )
	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 value = '[[' .. millenium .. '-ші мыңжылдық' .. bce .. '|' .. millenium .. '-ші мыңжылдық' .. bce .. ']]'
	if categoryNamePrefix then
		local catAction = (categoryNamePrefix == 'birth' and 'туғандар') or 'қайтыс болғандар'
		return value .. '[[Category:' .. millenium .. '-ші мыңжылдықта ' .. catAction .. bce .. ']]'
	else
		return value
	end
end

local function formatDateImpl( value, options, microformatClass, categoryPrefix, leftBracket, rightBracket, nolinks )
	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 ) end	
	if precision == 7 then return formatCentury( structure, categoryPrefix ) end
	if precision == 8 then return formatDecade( structure, categoryPrefix ) 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
	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 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 )
			local value = context.wrapSnak( formattedDate, qNotSoonerThan.hash ) .. '&nbsp;бұрын емес'
			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 )
			local value = context.wrapSnak( formattedDate, qNotLaterThan.hash ) .. '&nbsp;кейін емес'
			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, '[[Category:Туған жылы белгісіз тұлғалар]]' )
	if value then return value end

	options['conjunction'] = '&#32;немесе&#32;'
	options['value-module'] = 'Wikidata/date'
	options['value-function'] = 'formatBirthDate'
	options.i18n.somevalue = '\'\'белгісіз\'\'[[Category:Туған жылы белгісіз тұлғалар]]'
	
	local result = context.formatStatementDefault( context, options, statement )
	local bTable = { parseClaim( statement ) }
	local dTable = parseProperty ( context, options, 'P570' )

	if ( bTable and not dTable ) then
		local ageVal = ageCurrent( bTable )
		if ( ageVal ) then
			if ( options.suppressAge == nil or options.suppressAge == '' ) then
				result = result .. ' <span style="white-space:nowrap;">(' .. ageVal .. ' жас)</span>'
			end
			if ( not options.nocat and ageVal >= 0 ) then
				result = result .. '[[Category:Тірі тұлғалар]]'
			end
		end
	end
	return result
end

function p.formatDateOfDeathClaim( context, options, statement )
	local value = formatApproximateDateClaim( context, options, statement, '[[Category:Қайтыс болған жылы белгісіз тұлғалар]]' )
	if value then return value end

	options['conjunction'] = '&#32;немесе&#32;'
	options['value-module'] = 'Wikidata/date'
	options['value-function'] = 'formatDeathDate'
	options.i18n.somevalue = '\'\'белгісіз\'\'[[Category:Қайтыс болған жылы белгісіз тұлғалар]]'

	local result = context.formatStatementDefault( context, options, statement )
	local bTable = parseProperty ( context, options, 'P569' )
	local dTable = { parseClaim( statement ) }

	if ( bTable and dTable ) then
		local ageVal = age( bTable, dTable )
		if ( ageVal and (options.suppressAge == nil or options.suppressAge == '') ) then
			result = result .. ' <span style="white-space:nowrap;">(' .. ageVal .. ' жас)</span>'
		end
	end
	return result
end

function p.formatBirthDate( context, options, value )
	local microformatClass = (options.microformat ~= '-' and (options.microformat or 'bday')) or nil
	local cat = (not options.nocat and 'birth') or nil
	return formatDateImpl( value, options, microformatClass, cat, options.leftBracket, options.rightBracket, options.nolinks )
end

function p.formatDeathDate( context, options, value )
	local microformatClass = (options.microformat ~= '-' and (options.microformat or 'dday')) or nil
	local cat = (not options.nocat and 'death') or nil
	return formatDateImpl( value, options, microformatClass, cat, options.leftBracket, options.rightBracket, options.nolinks )
end

function p.formatDate( context, options, value )
	local microformatClass = options.microformat or nil
	local categoryPrefix = (not options.nocat and options.categoryPrefix) or nil
	return formatDateImpl( value, options, microformatClass, categoryPrefix, options.leftBracket, options.rightBracket, options.nolinks )
end

function p.formatDateIntervalProperty( context, options )
	local WDS = require( 'Module:WikidataSelectors' )
	local fromProperty = (options.from and options.from ~= '') and options.from or options.property
	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 _, claim in ipairs( fromClaims ) do
			table.insert( formattedFromClaims, context.formatStatement( options, claim ) or '' )
		end
	end

	local formattedToClaims = {}
	local toOptions = deepcopy( options )
	toOptions.property = options.to
	toOptions.novalue = nowLabel
	if toClaims then
		for _, claim in ipairs( toClaims ) do
			table.insert( formattedToClaims, context.formatStatement( toOptions, claim ) or '' )
		end
	end

	local fromOut = mw.text.listToText( formattedFromClaims, options.separator, options.conjunction )
	local toOut = mw.text.listToText( formattedToClaims, options.separator, options.conjunction )

	local out = ''
	if fromOut ~= '' or toOut ~= '' then
		out = (fromOut ~= '' and fromOut or '?') .. (toOut ~= '' and ' — ' .. toOut or ' бастап')
	end
	return out
end

function p.formatAsJulian( julTimeISO8601, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
	julTimeISO8601 = mw.text.trim( julTimeISO8601:gsub('^+', '') )
	local julTime = parseISO8601( julTimeISO8601 )
	local t = os.date( "*t", julTime )
	return moduleDates.formatWikiImpl( t, t, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks )
end

return p