మాడ్యూల్:Wikidata/Dates

వికీపీడియా నుండి
Jump to navigation Jump to search
local p = {}
local formatDate = require "Module:Complex date"
local tools = require "Module:Wikidata/Tools"
local defaultlang = mw.getCurrentFrame():callParserFunction("int", "lang")

local function splitTimestamp(timestamp, calendar)
	local pattern = "(%W)(%d+)%-(%d+)%-(%d+)"
	local era, year, month, day = timestamp:match(pattern)

	if calendar == 'julian' then
	--todo  year, month, day = formatDate.gregorianToJulian( era .. year, month, day )
	end

	return era, year, month, day
end

local function dateObject(snak, params) --[[
	transforms a Wikibase snak into a simpler table readable by Module:Complex date
		{
		type = "dateobject"
		valuetype = corresponds to the snaktype (value, somevalue or novalue)
		year = number
		month = number
		day = number
		calendar = julian or gregorian
		}
	]]--
	if not params then
		params = {}
	end
	local obj = {type = "dateobject", valuetype = snak.snaktype}
	if snak.snaktype == "value" then
		local value =  tools.getValue(snak)
		obj.era, obj.year, obj.month, obj.day = splitTimestamp(value.time, value.calendar)
		obj.precision = params.precision or value.precision
	end
	return obj
end

local function rangeObject(begin, ending)
	-- object containing one or two dateobject {type = "rangeobject", begin = dateobject, ending = rangeobject}
	local timestamp
	if begin then
		timestamp = begin.timestamp
	elseif ending then
		timestamp = ending.timestamp
	end
	return {begin = begin, ending = ending, timestamp = timestamp, type = 'rangeobject'}
end

-- Functions transforming dateobjects into date strings

local function standardDisplay(obj, precision, lang) -- returns a date in a natural language string
	if obj.valuetype == "somevalue" then
		return formatDate._complex_date("unknown", "", "", "", "", "", "", "", "", lang)
	elseif obj.valuetype == "novalue" then
		return "" -- ?
	end

	if precision >= 11 then
		return formatDate._complex_date("", "", obj.year .. '-' .. obj.month .. '-' .. obj.day, "", "", "" , "", "", "", lang)
	elseif precision == 10 then
		return formatDate._complex_date("", "", obj.year .. '-' .. obj.month, "", "", "" , "", "", "", lang)
	elseif precision == 9 then
		return formatDate._complex_date("", "", obj.year, "", "", "" , "", "", "", lang)
	elseif precision == 8 then
		return formatDate._complex_date("", "",  string.sub(tostring(obj.year), 1, 3) .. '0', "decade", "", "" , "", "", "", lang)
	elseif precision == 7 then
		return formatDate._complex_date("", "", string.sub(tostring(obj.year + 100), 1, 2), "century", "", "" , "", "", "", lang)
	end
end

--- ISO format
local function ISOdate(obj, precision)
	local str = ""
	if obj.valuetype ~= 'value' then
		return nil
	end
	if (precision >= 9) then
		str =  obj.year
	end
	if (precision >= 10) then
		str = str .. "-" .. obj.month
	end
	if (precision >= 11) then
		str = str .. "-" .. obj.day
	end
	return str
end

local function formatDatepoint(obj, params) -- takes in "datobject" and transforms it into a string
	if not obj then
		return nil
	end
	if not params then
		params = {}	
	end
	local lang = params.lang or defaultlang
	local precision
 	if obj.valuetype == "value" then
		precision = math.min(obj.precision, params.precision or 15)
	end

	if params.displayformat == "year" then
		return obj.year
	elseif params.displayformat == "isodate" then
		return ISOdate(obj, precision)
	else
		return standardDisplay(obj, precision, lang)
	end
end

local function formatDaterange(obj, params) --takes "rangeobject" and transforms it into a string
	local begin = formatDatepoint(obj.begin, params)
	local ending = formatDatepoint(obj.ending, params)
	local str = ""
	if begin then
		str = str .. "from " .. begin
	end
	if begin and ending then
		str = str .. " "
	end
	if ending then
		str = str .. "until " .. ending
	end
	return str
end

local function objectToText(obj, params) -- takes any date table and transforms it into a string 
	if obj.type == 'dateobject' then
		return formatDatepoint(obj, params)
	elseif obj.type == 'rangeobject' then
		return formatDaterange(obj, params)
	end
	return nil
end

-- Functions retrieving data from Wikidata

local function getDatefromQualif(statement, qualif)
	if not(tools.hasqualifier(statement, qualif) )then
		return nil
	end
	local v = statement.qualifiers[qualif][1]
	if v.snaktype ~= 'value' then
		return nil -- ?
	end
	return dateObject(v)
end

function p.getDate(statement) -- looks for a date in a statement (either qualifiers or main value) and returns it in the form of a "dateobject" or a "rangeobject"
	-- try to use qualifiers, that can have more accurate values than the main snak
	local period = getDatefromQualif(statement, 'P585') -- retourne un dateobject
	if period then
		return period
	end
	local begin, ending = getDatefromQualif(statement, 'P580'),  getDatefromQualif(statement, 'P582')
	if begin or ending then
		return rangeObject(begin, ending) -- a rangeobject contains two dates
	end
	local begin, ending = getDatefromQualif(statement, 'P1319'),  getDatefromQualif(statement, 'P1326')

	local obj
	if begin or ending then
		return rangeObject(begin, ending) -- should have another parameter stating that these are not the same as with usual qualifs
	end

	-- else, if the main value is a time value, then return it
	local mainsnak = statement.mainsnak
	if mainsnak.datatype ~= 'time' then
		return nil -- if the property datatype is not time, then do not use it
	end
	local params
	return dateObject(mainsnak, params)		
end

function p.getFormattedDate(statement, params)
	if not statement then
		return nil
	end
	local str

	local datetable = p.getDate(statement)
	if datetable then
		str = objectToText(datetable, params)
	end	

	local fuzzy = tools.hasqualifier(statement, {"P1480"}, {"Q5727902"}) -- should be moved to the getDate function
	if fuzzy then
		fuzzy = true
	end
	if fuzzy then
		str = formatDate._complex_date("", "circa", str)
	end
	return str
end

function p.formatTimeSnak(snak, params)
	local displayformat = params.displayformat
	if displayformat == 'raw' then
		return snak.datavalue.value.time
	end
	local dateobj = dateObject(snak)
	return objectToText(dateobj, params)
end

return p