Aller au contenu

Module:Wikidata/Dates

Une page de Wikipédia, l'encyclopédie libre.
Ceci est une version archivée de cette page, en date du 11 janvier 2014 à 23:58 et modifiée en dernier par Zolo (discuter | contributions) (ah en fait, ce qu'il y a en vrai dans Wikidata est mieux que ce qui est affiché là bas !). Elle peut contenir des erreurs, des inexactitudes ou des contenus vandalisés non présents dans la version actuelle.

 Documentation[créer] [purger]
-- sert à récupérer des données usuelles sur Wikidata (les fonctions élémentaires pour l'extraction des données se fait sur Module:Wikidata
-- ce module peut-être appelé par Module:InfoboxBuilder/Helpers qui les met en infobox

local wikidata = require( 'Module:Wikidata')
local formatdate = require( 'Module:Date')

local p = {}

function p.keydate( event, item, formatting ) -- récupère les valeurs contenues dans des qualificatifs, logique assez différente de pour les propriété principales
    if event == 'all' then event = nil end
    if not formatting then formatting = {} end -- pour ne pas avoir à vérifer à chaque fois que la table existe
    local claims = wikidata.getClaims({property = 'p793', targetvalue = event})
	
	if not claims or not claims[1] then
    	return nil
    end
    local datelist = {} -- crée une liste d'objets dateobject et daterange
   
    --[[accepte plusieurs date pour un même événement, mais doivent être dans des déclarations distinctes
 	note: les tables Wikidata on une clé 0 #table n'est donc pas fiable ]]--
    for i, j in pairs(claims) do
		local qualif = j.qualifiers
		
        if not j.qualifiers then break end
        local label = mw.wikibase.label( "Q" .. j.mainsnak.datavalue.value['numeric-id'])
        if qualif['p805'] then -- dedicated item - create a link
        	dedicated = 'Q' .. qualif['p805'][0].datavalue.value['numeric-id']
        	link = mw.wikibase.sitelink( dedicated )
        	if not link then link = 'wikidata:' .. dedicated end
        	label = '[[' .. link .. '|' .. label .. ']]'
        end

        if qualif['p585'] and not qualif['p585'][1] then
        	object = qualif['p585'][0].datavalue.value
        	object.label = label
        	object = p.dateobject(object)
        	table.insert(datelist, object)
        elseif qualif['p580'] and qualif['p582'] and not qualif['p580'][1] and not qualif['p582'][1] then
        	begin = p.dateobject(qualif['p580'][0].datavalue.value)
        	ending = p.dateobject(qualif['p582'][0].datavalue.value)
        	object =  p.daterange(begin, ending, label)
        	table.insert(datelist, object)
        elseif qualif['p580'] and not qualif['p580'][1] then
        	begin = p.dateobject(qualif['p580'][0].datavalue.value)
        	ending = nil
        	object = p.daterange(begin, ending, label)
        	table.insert(datelist, object )
        elseif qualif['p582'] and not qualif['p582'][1] then
        	begin = nil
        	ending = p.dateobject(qualif['p582'][0].datavalue.value)
        	object = p.daterange(begin, ending, label)
        	table.insert(datelist, object)
       	end
	end

	table.sort(datelist, function(a,b) return a.timestamp < b.timestamp end)
	for i, j in pairs(datelist) do
		datelist[i] = p.objecttotext(j, formatting)
	end
	return mw.text.listToText(datelist, formatting.separator, formatting.conjunction)
end

function p.keydatewithfallback(event, fallback)
	local firstevent = p.keydate(event)
	if firstevent then
		return firstevent
	end
	if not fallback then
		return nil
	end
	local eventlist = {} -- liste tous les événement pertinents (créer une option pour ne retourner que le premier dans la liste ?)

	for i, j in pairs(fallback) do
		local current = p.keydate(j)
		if current and current ~= '' then
			table.insert(eventlist, wikidata.formatEntityId(j) .. ' : ' .. current)-- indique le nom du l'événement pour éviter les imprécisions
		end
	end
	return mw.text.listToText(eventlist)
end

function p.from(d)  -- retourne "à partir de date" en langage naturel
	if d.year then year = d.year end
	if d.month then month = d.month end
	if d.day then day = d.day end
	
	if day then 
		return 'à partir du ' .. datestring
	elseif tonumber(month) == 4 or tonumber(month) == 8  or tonumber(month) == 10 then -- mois commençant par une voyelle
		return 'à partir d\'' .. datestring
	else return 
		'à partir de ' .. datestring
	end
end

function p.todate(d)  -- retourne "jusqu'à date' en langage naturel
	local year = d.year
	local month = d.month
	local day = d.day
	local datestring = d.datestring
	
	if day then 
		return 'jusqu\'au ' .. datestring
	else return 
		'jusqu\'à' .. datestring
	end
end

function p.rangetotext(begin, ending)
	if not begin or not ending then return error end
	
	local beginstring = begin.datestring
	local endstring = ending.datestring
	
	if begin.day then day1 = begin.day end
	if begin.month then month1 = begin.month end
	if begin.year then year1 = begin.year end

	if ending.day then day2 = ending.day end
	if ending.month then month2 = ending.month end
	if ending.year then year2 = ending.year end
       
   	if year1 and year2 and (year1 == year2) then -- évite de répéter l'année si c'est deux fois la même
   		return formatdate.modeleDate({day1, month1}) .. '-' .. endstring
    else
    	return  beginstring .. '-' .. endstring
    end     
 end
 
 function p.dateobject(orig) --prend une table de date Wikibase, et la retourne sous un format plus manipulable
 	local label = orig.label
 	local timestamp = orig.time
	local precision = orig.precision
	local era = '+' -- (after Christ)
	if string.sub(timestamp,1,1) == '-' or  string.sub(timestamp,2,12) == '00000000000' then  -- Before Christ or year 0 (see datamodel)
		era = '-' 
	end 
	local year = nil
	local datestring = ''
	
	local calendar = 'gregorian' -- calendar for display, not storage
	if orig.calendarmodel == 'http://www.wikidata.org/entity/Q1985786' then
		calendar = 'julian'
		year, month, day = formatdate.gregorianToJulian( era .. year, month, day )
	end
		
	if precision == 7 or precision == 8 then
		-- texte spécial pour précision = décennie
		--[[ noter que précision = "decade" sur Wikidata, l'équivalenet GUI de precision == 8, ne veut pas forcément dire une décennie ronde
		1957, precision = 8 est affiché comme 1950s sur Wikidata, mais il parait préférable de l'afficher comme "vers 1957"
		mais que faire pour precision == 7 ?
		]]
		local decade = string.sub(timestamp, 9, 12)
		if era == '-' then -- remove one Year for BC years because of year 0
			decade = tostring(tonumber(decade) + 1)
		end
		if string.find(decade, '0') == 1 then -- enlève les zéros au début, à corriger pour enlever 2 zéros si besoin
			decade = string.sub(decade, 2, 4) 
		end
		datestring = 'vers ' .. decade
		return {type='dateobject', timestamp = timestamp, era= era, calendar=calendar, label=label, datestring = datestring}
	end
	
	if precision >= 9 then 
		year = string.sub(timestamp, 9, 12)
		if era == '-' then -- remove one Year for BC years because of year 0
			year = tostring(tonumber(year) + 1)
		end
	end
	local month = nil
	if precision >= 10 then
		month = string.sub(timestamp, 14, 15)
	end
	local day = nil
	if precision >= 11 then
		day = string.sub(timestamp, 17, 18)
	end
	datestring = formatdate.modeleDate({day, month, year})
	return {type='dateobject', timestamp = timestamp, year=year, month=month, day=day, era= era, calendar=calendar, label=label, datestring = datestring}
end

function p.daterange(date1, date2, label)
	if date1 then
		if date1.type ~= 'dateobject' then return error end
	end
	if date2 then 
		if date2.type ~= 'dateobject' then return error end
	end
	if date1 and date2 then
		if date1.timestamp > date2.timestamp then return error end -- ne pas inverser les dates, c'est sans doute un erreur
	end
	if date1 then timestamp = date1.timestamp else timestamp = date2.timestamp end
	return {type='daterange', timestamp = timestamp, begin = date1, ending = date2, label = label}
end

function p.objecttotext(object, formatting)
	text = '' 
	if object.type == 'dateobject' then
		text = text .. object.datestring
	elseif object.type == 'daterange' then
		if object.begin and object.ending then
			text = text .. p.rangetotext(object.begin, object.ending)
		elseif object.begin then
			rtext = text .. p.from(object.begin)
		elseif object.ending then
			text = text .. p.todate(object.ending)
		end
	else
		return error
	end
	if formatting and formatting.showlabel == 'true' then 
		text = text .. ' : ' .. object.label
	end
	return text 
end	

function p.duration(range)
	if not range.begin and range.ending then
		return nil
	else 
		a, b = range.begin, range.ending
	end
	return formatdate.age(a.year, a.month, a.day, b.year, b.month, b.day)
end

return p