Module:Dâta

De Vouiquipèdia, l’enciclopèdia abada.
Sauter à la navigation Sauter à la recherche

La documentation pour ce module peut être créée à Module:Dâta/doc

local fun = {}

local Outils = require 'Module:Outils'
local Yesno = require 'Module:Yesno'
-- chargement de la base de donnée répertoriant certaines pages existant ou n'existant pas pour éviter les "ifexist".
local dataLims
local success, resultat = pcall ( mw.loadData, 'Module:Dâta/Data' )
if success then
	dataLims = resultat
else
	-- protection au cas ou le sous module serait mal modifié
	dataLims = { [''] = { mes = { nion = 1000, tos = { 1773, 2014 } }, } }
end

-- nettoie un paramètre non nommé (vire les espaces au début et à la fin)
-- retourne  nil si le texte est vide ou n'est pas du texte. Attention c'est important pour les fonction qui l'utilise.
local trim = Outils.trim

-- Fonction destiné à mettre la première lettre du mois en majuscule du mois : 
-- utilisation de string car aucun mois ne commance par une lettre non ascii en français ou anglais. 
local function ucfirst( str )
	return str:sub( 1, 1 ):upper() .. str:sub( 2 )
end

local modeloPremier = '<abbr class="abbr" title="premiér">1<sup>ér</sup></abbr>'


-- liste des mois, écriture exacte et alias, en minuscule
local listaMes = {
	{ num = 1,  nJorn = 31, abrev = 'janv.',  nom = 'de janviér', alias = { 'janviér', 'janvier', 'jan.', 'jan', 'janv.', 'janv', 'january' } },
	{ num = 2,  nJorn = 29, abrev = 'fev.',   nom = 'de fevriér', alias = { 'fevriér', 'fevrier', 'fev.', 'fev', 'fevr.', 'fevr', 'feb', 'february' } },
	{ num = 3,  nJorn = 31, abrev = 'mârs',   nom = 'de mârs', alias = { 'mârs', 'mâr.', 'mâr', 'mar.', 'mar', 'march' } },
	{ num = 4,  nJorn = 30, abrev = 'avr.',   nom = 'd’avril', alias = { 'avril', 'avr.', 'avr', 'apr', 'april'} },
	{ num = 5,  nJorn = 31, abrev = 'mê',    nom = 'de mê', alias = { 'mê', 'me', 'may' } },
	{ num = 6,  nJorn = 30, abrev = 'jouin',   nom = 'de jouin', alias = { 'jouin', 'jun', 'june' } },
	{ num = 7,  nJorn = 31, abrev = 'july.', nom = 'de julyèt', alias = { 'julyèt', 'julyet', 'july.', 'july', 'jul', 'july' } },
	{ num = 8,  nJorn = 31, abrev = 'oût',   nom = 'd’oût', alias = { 'oût', 'aug', 'august' } },
	{ num = 9,  nJorn = 30, abrev = 'sept.',  nom = 'de septembro', alias = { 'septembro', 'sept.', 'sept', 'sep.', 'sep', 'september' } },
	{ num = 10, nJorn = 31, abrev = 'oct.',   nom = 'd’octobro', alias = { 'octobro', 'oct.', 'oct', 'october' } },
	{ num = 11, nJorn = 30, abrev = 'nov.',   nom = 'de novembro', alias = { 'novembro', 'nov.', 'nov', 'november' } },
	{ num = 12, nJorn = 31, abrev = 'dèc.',   nom = 'de dècembro', alias = { 'dècembro', 'decembro', 'dèc.', 'dèc', 'dec.', 'dec', 'december' } },
	out = { num = 8, nJorn = 31, abrev = 'out', nom = 'd’oût', alias = { 'out' }  },
}

-- ajoute les noms, abreviations et alias en tant que clé de listeMois
for i = 1, 12 do
	local mes = listaMes[ i ]
	listaMes[ tostring( i ) ] = mes
	listaMes[ '0' .. i ] = mes
	listaMes[ mes.nom ] = mes
	listaMes[ mes.abrev ] = mes
	for _, n in ipairs( mes.alias ) do
		listaMes[ n ] = mes
	end
end
for _, n in ipairs( listaMes.out.alias ) do
	listaMes[ n ] = listaMes.out
end
fun.listaMes = listaMes

local lista_sesons = {
	{ 'forél', 'spring', },
	{ 'chôd-temps', 'summer', },
	{ 'ôton', 'autumn', },
	{ 'hivèrn', 'winter', },
}

---
-- valide que la chaîne passée est un mois valide.
-- retourne le nom complet ou nil si non reconnu
-- si reconnu, retourne aussi le numéro du mois [1-12]
function fun.valideMes( mes )
	local m = trim( mes )
	if m then
		m = mw.ustring.lower( m )
		if listaMes[ m ] then
			return listaMes[ m ].nom, listaMes[ m ].num
		end
	end
end

---
-- valide que la chaîne passée est une saison valide.
-- retourne le nom complet ou nil si non reconnu
function fun.valideSeson( seson )
	local s = trim( seson )
	if s then
		s = mw.ustring.lower( s )
		for i = 1, 4 do
			for _, n in ipairs( lista_sesons[i] ) do
				if s == n then
					return lista_sesons[i][1]
				end
			end
		end
	end
end

---
-- determinationMois trouve le numéro du mois et son nom,
-- à partir de son nom, de son numéro ou d'une expression mathématique.
-- Si le deuxième paramètre est vrai, les nombres supérieur à 12 ou non entiers sont acceptés.  
function fun.determinacionMes( mes, mod, boclla )
	local num, nom
	if tonumber( mes ) then
		num = math.floor( tonumber( mes ) )
		if mod then			
			-- si le nombre du mois est calculé par une exression, le résultat peut être supérieur à 12, ou inférieur à 1
			num = math.fmod( num + 239, 12 ) + 1  -- +239 car fmod(-1) = -1 et non 11 
		elseif num < 1 or num > 12 then
			num = nil
		end
	elseif trim( mes ) then
		nom, num = fun.valideMes( mes )
		if nom == nil and boclla == nil then
			-- essai de détermination d'un nombre avec le parser #expr de Mediawiki.
			-- le paramètre boucle évite de tourner en boucle.
			nom, num = fun.determinacionMes( mw.getCurrentFrame():callParserFunction( '#expr', mes ), true, true )
		end
	end
	if num and not nom then
		nom = listaMes[ num ].nom
	end
	return nom, num
end


--  fonction interne à modeleDate, pour déterminer si on peut se passer de faire un ifexit
local function existData( dataQualificatif, an, mes )
	local data
	if mes then
		data = dataQualificatif.mes
	else
		data = dataQualificatif.an
	end
	if type( data ) ~= 'table' then
		-- si data n'existe pas c'est que l'on considère qu'il n'y a pas de lien.
		return
	end
	-- le qualificatif est remplacer par celui de la base de donnée, ce qui permet des alias.
	local lim = an .. ' ' .. ( dataQualificatif.qualificatif or '' )
	local solet = an
	if mes then
		lim = mes .. ' ' .. lim
		solet = ucfirst( mes ) .. ' ' .. an
	end
	local nion = tonumber( data.nion )
	if nion and an <= nion then
		-- si la l'année est dans la partie 'aucun' on teste s'il y a malgré tout un lien isolé
		if type( data.solet ) == 'table' then
			for i, v in ipairs( data.solet ) do
				if solet == v or solet == tonumber( v ) then
					return lim
				end
			end
		end
		-- partie aucun et pas de lien => nil
		return nil
	elseif type( data.tos ) == 'table' then
		local tos1, tos2 = tonumber( data.tos[1] ), tonumber( data.tos[2] )
		if tos1 and tos2 and an >= tos1 and an <= tos2 then
			-- l'année est dans la partie 'tous' donc on retourne le lien
			return lim
		end
	end
	-- l'annee n'est ni dans la partie aucun, ni dans la partie tous donc il faut tester si la page existe.
	local cibaLim = mw.title.new( lim )
	if cibaLim and cibaLim.exists then
		return lim
	end
end

---
-- Supprime le jour de la semaine, et "le" avant une date
function fun.neteyajoJorn( jorn )
	if type( jorn ) == 'string' then
		local nomJorn = { '[Dd]elon', '[Dd]emârs', '[Dd]emécro', '[Dd]ejô', '[Dd]evendro',
			'[Dd]essando', '[Dd]emenge', '^ *[Ll]o', '^ *[Ll]e', '^ *[Ll]a' }
		local premier = { '<abbr class="abbr" title="[Pp]remiér" ?>1<sup>ér</sup></abbr>', '1<sup>ér</sup>', '1ér' }
		for i, v in ipairs( nomJorn ) do
			jorn = jorn:gsub( v, '' )
		end
		for i, v in ipairs( premier ) do
			jorn = jorn:gsub( v, '1' )
		end
		jorn = trim( jorn )
	end
	return jorn
end

---
-- Sépare une chaine date en un table contenant les champs jour, mois et annee.
-- la date doit contenir le mois.
function fun.separacionJornMesAn( date )
	date = trim( date )
	if date then
		local function fota( temps, valor )
			return false, '<span class="error">' .. temps .. ' pas justo (' .. valor .. ')</span>'
		end
		local jorn, mes, an, cachierMes, cachierAn, separator
		-- variable pour construire les regex
		local j = '([0-3]?%d)'      -- jour
		local m = '([01]?%d)'       -- mois numérique
		local mmm =  '([^%s%p%d]+[.]?)' -- mois en toute lettre
		local aj = '(%-?%d+)'       -- année ou jour
		local s = '[ ./-]+'          -- séparateur simple
		local sep = '([ ./-]+)'      -- séparateur avec capture, pour le détecter deux fois
		local muens = '(%-?)'        -- signe moins pour signifier qu'il ne faut pas afficher cette donnée
		local regexb = {
			jmmm = '^'..j..s..mmm..muens..'$',
			mmmjva = '^'..mmm..s..j..', ?'..aj..'$',
		}
		
		date = fun.neteyajoJorn( date )
		-- suppression catégorie, liens, balises
		date = mw.ustring.gsub( date, '%[%[[Cc]at[èe]gor[yi]e?:.-%]%]', '' ) 
		date = date	:gsub( '%b<>', '' )
					:gsub( '%[%[([^%[%]|]*)|?([^%[%]]*)%]%]', function ( l, t ) return trim( t ) or l end )
		-- suppression des espaces insécables
					:gsub( '\194\160', ' ' )
					:gsub( '&nbsp;', ' ' )
					:gsub( '\226\128\175', ' ' )
					:gsub( '&nnbsp;', ' ' )
					:gsub( '\226\128\137', ' ' )
					:gsub( '&thinsp;', ' ' )
					:gsub( '&#32;', ' ' )
					:gsub( ' +', ' ' )
		-- réduction av. J-C pour simplifier un peu les regex :
					:gsub( '(%d+) ?[Dd][Vv]%.? ?[Jj][ .-]*[Cc]%.?', '-%1' )
		-- supression de l'heure dans les date ISO
					:gsub( '^+?([%d-]*%d%d%-%d%d)T%d%d[%d:,.+-]*Z?$' , '%1')
		
		-- test année seule
		if date:match( '^'..aj..'$' ) then
			an = date:match( '^'..aj..'$' )
		elseif date:match( '^'..aj..s..aj..muens..'$' ) then
			-- jj/mm, mm/aaaa ou aaaa/mm 
			local a, separator, b, sb = date:match( '^'..aj..sep..aj..muens..'$' )
			a, b = tonumber( a ), tonumber( b )
			if separator:match( '^.+%-$' ) then
				-- probablement mm/-aaaa, année av.JC
				b = 0 - b
			end
			if  a > 12 and ( b < 1 or b > 31 ) or
				b > 12 and ( a < 1 or a > 31 ) then
				return fota( 'Dâta', date )
			elseif b < 1 or b > 31 then
				mes, an, cachierAn = a, b, sb 
			elseif a < 1 or a > 31 then
				an, mes  = a, b
			elseif b > 12 then
				return fota( 'Mês', b )
			else
				jorn, mes, cachierMes = a, b, sb
			end
		elseif date:match( '^'..aj..sep..m..muens..'%2'..aj..muens..'$' ) then
			-- jj/mm/aaaa ou aaaa/mm/jj
			jorn, separator, mes, cachierMes, an, cachierAn =  date:match( '^'..aj..sep..m..muens..'%2'..aj..muens..'$' )
			if separator == '-' and cachierMes == '-' and cachierAn == '' and tonumber( an ) > 0 then
				-- date au format jj-mm--aaaa type 17-06--44 pour 17 juin 44 av. JC
				cachierMes = nil
				an = 0 - an
			end
		elseif date:match( '^'..j..sep..mmm..muens..'%2'..aj..muens..'$' ) then
			-- jj mmm aaaa
			jorn, separator, mes, cachierMes, an, cachierAn = date:match( '^'..j..sep..mmm..muens..'%2'..aj..muens..'$' )
		elseif date:match( '^'..mmm..s..aj..muens..'$' ) then
			-- mmm aaaa
			mes, separator, an, cachierAn = date:match( '^'..mmm..sep..aj..muens..'$' )
			if separator:match( '^.+%-$' ) then
				an = '-' .. an
			end
		elseif date:match( '^'..j..s..mmm..muens..'$' ) then
			-- jj mmmm
			jorn, mes, cachierMes = date:match( '^'..j..s..mmm..muens..'$' )
		elseif date:match( '^'..mmm..s..j..', ?'..aj..'$') then
			-- mmm jj, aaaa (format anglo-saxon)
			mes, jorn, an = date:match( '^'..mmm..s..j..', ?'..aj..'$')
		elseif date:match( '^'..mmm..'$' ) then
			mes = date
		else
			return fota( 'Dâta', date )
		end
		local jn, ann = tonumber( jorn ), tonumber( an )
		if jn and ann and ( jn > 31 or jn < 0 or #jorn >= 3 ) and ann <= 31 then
			-- cas notamment des date ISO 2015-06-17, -0044-06-17 et -0002-06-17
			-- inversion du jour et de l'année
			local temp = an
			an = jorn
			jorn = temp
		end
		
		return fun.validacionJornMesAn{ 
			jorn, mes, an, 
			cachierAn = trim( cachierAn ) and true or nil, 
			cachierMes = ( trim( cachierAn ) or not an ) and trim( cachierMes ) and true or nil, 
			-- or nil sert juste à éviter de trainer une valeur false dans tous les tests unitaires.
		}
	else 
		return true, {}
	end
end


---
-- validationJourMoisAnnee vérifie les paramètres correspondent à une date valide.
-- la date peut être dans les paramètre 1 à 3, ou dans des paramètres jour, mois et annee.
-- La fonction retourne true suivit d'une table avec la date en paramètres nommé (sans accent sur année)
-- ou false suivit d'un message d'erreur.
function fun.validacionJornMesAn( frame, ... )
	local args = Outils.extractArgs( frame, ... )
	local jorn, mes, numMes, an
	local bjorn = args[1] or args['jorn'] or ''
	local bmes = tostring( args[2] or args['mês'] or '' )
	local ban = args[3] or args['an'] or ''
	
	local function fota( temps, valor )
		return false, '<span class="error">' .. temps .. ' pas justo (' .. valor .. ')</span>'
	end
	
	-- on traite l'année
	if Outils.notEmpty( ban ) then
		an = tonumber( ban )
		if an == nil and type( ban ) == 'string'  then
			-- test si l'année contient av. J.-C.
			an = string.match( string.upper( ban ), '^(%d+) ?[Aa][Vv]%.? ?[Jj][ .-]*[Cc]%.?' )
			an = tonumber( an )
			if an then
				an = 0 - an
			else
				return fota( 'An', ban )
			end
		elseif an == 0 then
			return fota( 'An', 0 )
		end
	else
		an = nil
	end
	
	-- on traite le mois
	if Outils.notEmpty( bmes ) then
		mes, numMes = fun.determinacionMes( bmes )
		if mes == nil then
			mes = fun.valideSeson( bmes )
			if mes == nil then
				return fota( 'Mês', bmes )
			end
		else		
			-- on traite le jour si présent
			if Outils.notEmpty( bjorn ) then
				jorn = tonumber( bjorn )
				if jorn == nil then
					jorn = tonumber( fun.neteyajoJorn( bjorn ) )
				end
				if jorn == nil then
					return fota( 'Jorn', bjorn )
				end
				-- on valide que le jour est correct
				if jorn < 1 or jorn > 31 then
					return fota( 'Jorn', bjorn )
				elseif jorn > listaMes[numMes].nJorn then
					return fota( 'Jorn', bjorn .. ' ' .. mes )
				elseif jorn == 29 and numMes == 2 and an and ( math.fmod( an, 4 ) ~= 0 ) then
					-- l'année bisextile sur les siècles est toujours acceptée pour être compatible avec les dates juliennes.
					return fota( 'Jorn', '29 de fevriér ' .. an  )
				end
			else
				-- S'il n'y a pas de jour on regarde si la première lettre du mois est en majuscule
				if bmes:match( '^%u' ) then
					-- oui, on passe la première lettre en majuscule
					mes = ucfirst( mes )
				end
				-- s'il n'y a pas d'année non plus on retourne le mois simple
			end
		end
	else
		-- on teste le jour si présent
		if Outils.notEmpty( bjorn ) then
			if an then
				return fota( 'Mês', 'absent' )
			else
				bjorn = fun.neteyajoJorn( bjorn )
				jorn = tonumber( bjorn )
				if jorn then
					if jorn > 31 or jorn < 1 then
						an = jorn
						jorn = nil
					else
						return fota( 'Dâta', 'jorn solèt : ' .. bjorn )
					end
				else
					return fota( 'Jorn', bjorn )
				end
			end
		end	
	end
	
	-- vérification de l'absence d'un décalage
	if an and an < 13 and an > 0 and not jorn and ( tonumber( bmes ) or (not mes and tonumber( args[4] ) ) ) then
		return false, '<span class="error">an emprobâblo (' .. an .. ')</span>'
	end
		
	local resultat = {
		jorn = jorn,
		mes = mes,
		numMes = numMes,
		an = an,
		cachierAn = args.cachierAn, 
		cachierMes = args.cachierMes,
	}
	return true, resultat
end


---
-- émule le modèle {{m|Date}}.
-- Paramètres :
--		1 : jour (numéro ou "1er") ou la date complète
--		2 : mois (en toutes lettres) ou spécialité de l'année
--		3 : année (nombre)
--		4 : spécialité de l'année
--		julien : date dans le calendrier julien
--		compact : affiche le mois sous forme d'abréviation
--		avJC : non pour désactiver l'affichage de « av. J.-C. » pour les date négatives
--		âge : ajout la durée depuis cette date
--		nolink : ne met pas de lien sur la date
--		naissance : ajoute la class "bday"
--		mort : ajoute la class "dday"
function fun.modeloData( frame )
	local args = Outils.extractArgs( frame )
	local cat, resultat = ''
	
	-- analyse des paramètres non nommés (ou paramètres de la date jour, mois, annee)
	local eprova, params
	local arg1, arg2, arg3 = fun.neteyajoJorn( args[1] ), trim( args[2] ), trim( args[3] )
	if type( arg1 ) == 'string' and arg3 == nil and ( arg1:match( '[^ ./-][ ./-]+[^ ./-]' ) or arg2 == nil or dataLims[arg2] or mw.ustring.match( arg2, '%a %a' ) ) then
		-- la date est dans le premier paramètre
		eprova, params = fun.separacionJornMesAn( arg1 )
		if eprova then
			params.qualificatif = arg2
		end
	else
		local function cachierParam( p )
			-- sépare le signe moins final éventuel signifiant que le paramètre ne doit pas être affiché.
			if type( p ) ~= 'string' then
				return p, nil
			end
			local value, mask = p:match( '^%s*(.-)(%-?)%s*$' )
			return value, ( mask == '-' or nil )
		end
		local cleanArgs = { arg1 or args.jorn }
		cleanArgs[2], cleanArgs.cachierMes = cachierParam( args[2] or args.mes )
		cleanArgs[3], cleanArgs.cachierAn = cachierParam( args[3] or args.an or args['an'] )
		mw.logObject( cleanArgs )
		eprova, params = fun.validacionJornMesAn( cleanArgs )
		if eprova then
			params.qualificatif = trim( args[4] )
		end
	end
	
	-- analyse des paramètres nommés
	if eprova then
		params.qualificatif = params.qualificatif or args.qualificatif
		-- julien peut avoir trois valeurs: inactif, format standard (true), format court
		params.jelien = Yesno( args.jelien, 'côrt', false )
		params.dvJC = Yesno( args.dvJC )
		
		local listaParam = {
			ajo = 'âjo',
			['âjo'] = 'âjo',
			nessence = 'nèssence',
			['nèssence'] = 'nèssence',
			mort = 'môrt',
			['môrt'] = 'môrt',
			nolinks = 'nolinks',
			compact = 'compact',
			compacto = 'compact',
		}
		for n, v in pairs( listaParam ) do
			params[v] = params[v] or Yesno( args[n], true, false ) or nil
		end
		
		-- sortie pour les tests unitaire, ou pour débuger
		if args.debug then
			return params
		end
		
		resultat = fun._modeloData( params )

	else
		local namespaceCategorisation = { [0] = true, [4] = true, [10] = true, [14] = true, [100] = true }
		if namespaceCategorisation[ mw.title.getCurrentTitle().namespace ] and not Outils.notEmpty( args.nocat ) then
			cat = '[[Catègorie:Pâge qu’emplèye lo modèlo dâta avouéc na sintaxa fôssa]]'
		end
		resultat = params .. cat
	end
	
	return resultat or ''
end

function fun._modeloData( args )
	local an, mes, numMes, jorn = args.an, args.mes, args.numMes, args.jorn
	local qualificatif = args.qualificatif
	
	if ( an or mes or jorn ) == nil then
		return
	end
	
	-- on traite l'age, naissance et mort
	local ajo = args['âjo'] and  fun.ajo( an, numMes, jorn )
	local nessece = args.nessence
	local mort = args.mort
	
	-- on traite le calendrier
	local gan, gmes, gjorn = an, numMes, jorn        -- date suivant le calendrier grégorien pour <time>
	local jan, jmes, jjorn = an, mes, jorn           -- date suivant le calendrier julien si necessaire
	local jelien, jelien2, jelien3, jelien4          -- servira éventuellement à a afficher la date selon le calendrier julien
	if an and jorn then
		local amj = an * 10000 + numMes * 100 + jorn
		if amj < 15821014 then
			if an > 0 then
				gan, gmes, gjorn = fun.julianToGregorian( an, numMes, jorn )
			else
				-- calendrier grégorien proleptique avec année 0.
				gan, gmes, gjorn = fun.julianToGregorian( an + 1, numMes, jorn )
			end
			args.jelien = false
		elseif args.jelien then
			gan, gmes, gjorn = fun.julianToGregorian( an, numMes, jorn )
			an, mes, jorn = gan, listaMes[gmes].nom, gjorn
			if jjorn == 1 then
				jjorn = modeloPremier
			end
			if args.compact then
				jmes = listaMes[ jmes ].abrev
			end
			jelien = mw.html.create( '' )
			if args.jelien == 'côrt' then
				jelien = jelien:tag( 'span')
						:addClass( 'nowrap' )
						:wikitext( jjorn, ' ', jmes, ' ' )
				if jan == an then
					jelien2 = '<sup>[[calendriér grègorien|grèg.]]</sup>'
				else
					jelien:wikitext( jan, ' ' )
					jelien3 = '<sup>[[calendriér grègorien|grèg.]]</sup>'
				end
				jelien = jelien:tag( 'sup' )
							:wikitext( '[[calendriér jelien|jel.]]' )
					:allDone()
					:wikitext( ' / ' )
			else
				jelien:tag( 'span')
						:addClass( 'nowrap' )
						:wikitext( jjorn, ' ', jmes, ' ', jan  )
						:done()
					:wikitext( ' (' )
				jelien4 = ' [[Passâjo du calendriér jelien u calendriér grègorien|dens lo calendriér grègorien]])'
			end
		end
	else
		if an and an < 0 then
			gan = gan + 1
		end
		args.jelien = false
	end
	
	-- on génère le résultat
	
	-- Déclarations des variables
	local wikiLista = {}                   -- reçois le texte affiché pour chaque paramètre
	local iso = {}                         -- reçois le format date ISO de ce paramètre
	local textoMes = mes                   -- texte du mois qui sera affiché (éventuellement l'abréviation)
	if args.compact then
		if args.nolinks then
			textoMes = '<abbr class=abbr title="' .. mes .. '">' .. listaMes[ mes ].abrev .. '</abbr>'
		else
			textoMes = listaMes[ mes ].abrev
		end
	end
	mes = mes and mes:gsub( 'out', 'oût' )
	
	local dataQualificatif, dataCat
	if not args.nolinks then
		dataQualificatif = dataLims[qualificatif or '']
		if type( dataQualificatif ) ~= 'table' then
			-- si le qualifiquatif n'est pas dans la base de donnée, on crée une table minimum,
			-- qui imposera un test sur l'annee, mais considère qu'il n'y a pas de lien sur le jour ou le mois
			dataQualificatif = { qualificatif = ' ' .. qualificatif, an = { } }
		end
		dataCat = dataLims[dataQualificatif.cat]
		if type( dataCat ) ~= 'table' or dataCat == dataQualificatif then
			dataCat = { qualificatif = '' }
		end
	end
	local function wikiLim( lim, texto )
		if lim == texto then 
			return '[[' .. texto .. ']]'
		else
			return '[[' .. lim .. '|' .. texto .. ']]'
		end	
	end
	

	-- le jour si présent
	local qualifJorn = ''
	if jorn then
		local textoJorn = jorn
		if args.nolinks then
			if jorn == 1 then
				jorn = modeloPremier
			end
			table.insert( wikiLista,  jorn )
		else
			qualifJorn = dataQualificatif.jorn and dataQualificatif.qualificatif
				or dataCat.jorn and dataCat.qualificatif
				or ''
			local lim = jorn .. ' ' .. mes .. ' ' .. qualifJorn
			if jorn == 1 then
				jorn = '1<sup>ér</sup>'
				lim = '1ér ' .. mes .. ' ' .. qualifJorn
			end
			-- s'il n'y a pas de lien sur le mois, il sera affiché avec le jour.
			table.insert( wikiLista,  wikiLim( lim, jorn ) )
			table.insert( wikiLista,  wikiLim( lim, jorn .. ' '.. textoMes ) )
		end
		table.insert( iso,  1, string.sub( '0' .. gjorn, -2 ) )
	end
	
	-- le mois
	if mes then
		if #wikiLista == 0 and an == nil then
			return textoMes
		end
		if args.nolinks then
			if not args.cachierMes then 
				table.insert( wikiLista,  textoMes )
			end
		else
			local lim
			if an then
				lim = existData( dataQualificatif, an, mes ) or existData( dataCat, an, mes )
				if lim == nil and qualificatif and qualifJorn == '' then
					-- test nouveau test sans le qualificatif uniquement s'il n'y a pas d'éphémérides pour ce qualificatif.
					lim = existData( dataLims[''], an, mes )
				end
			end
			if lim or args.cachierMes then
				-- s'il y a un lien on retire le lien affichant 'jour mois' pour ajouter '[[mois annee|mois']]
				table.remove( wikiLista )
				if not args.cachierMes then
					table.insert( wikiLista,  wikiLim( lim, textoMes ) )
				end
			elseif #wikiLista > 0 then
				-- sinon on retire le lien affichant 'jour' pour ne garder que le lien 'jour mois'
				table.remove( wikiLista, #wikiLista - 1 )
			elseif args.cachierAn then
				-- s'il n'y a pas de jour et que l'année n'est pas affichée, on insère le mois seul.
				table.insert( wikiLista,  textoMes )
			end
		end
		if gmes then
			table.insert( iso,  1, string.sub( '0' .. gmes, -2 ) )
		end
		table.insert( wikiLista, jelien2 )
	end
	
	-- l'année
	if an and not (args.jelien == true and args.nolinks and jan == an ) then
		if not args.cachierAn then
			local textoAn = an
			local lim
			if an < 0 then
				local anDvJc = 0 - an
				lim = lim or ( anDvJc .. ' dv. J.-C.' )
				if args.dvJC == false then
					textoAn = anDvJc
				else
					textoAn = anDvJc .. ' <abbr class="abbr" title="'
						.. anDvJc .. ' devant Jèsus-Crist">dv. J.-C.</abbr>'
				end
			end
			if args.nolinks then -- seulement si on doit l'affichée
				table.insert( wikiLista,  textoAn )
			else
				lim = existData( dataQualificatif, an ) or existData( dataCat, an ) or lim or an			
				if mes and #wikiLista == 0 then
					-- si le mois n'a pas de lien et n'est pas affiché avec le jour, il est affiché avec l'année.
					textoAn = textoMes .. ' ' .. textoAn
				end
				table.insert( wikiLista,  wikiLim( lim, textoAn ) )
			end
		end
		if gan > 999 then
			table.insert( iso,  1, gan )
		elseif gan > -1 then
			table.insert( iso,  1, string.sub( '000' .. gan , -4 ) )
		elseif gan > -999 then
			-- calendrier grégorien proleptique avec année 0.
			table.insert( iso,  1, 'U-' .. string.sub( '000' .. ( 0 - gan ), -4 ) )
		else
			table.insert( iso,  1, 'U' .. gan )				
		end
	end
	table.insert( wikiLista, jelien3 )

		
	-- l'age
	if type( ajo ) == 'number' and ajo >= 0 and ( not nessence or ajo < 120 ) then
		if ajo == 0 then
			ajo = '(muens d’un&nbsp;an)'
		elseif ajo == 1 then
			ajo = '(1&nbsp;an)'
		else
			ajo = '(' .. ajo .. '&nbsp;ans)'
		end
	else
		ajo = false
	end
	
	
	-- compilation du résultat
	local wikiTexto = table.concat( wikiLista, ' ' )
	local isoTexto = table.concat( iso, '-' )
	
	-- On ajoute un peu de sémantique.
	local wikiHtml = mw.html.create( '' )
			:node(jelien)
	
	local dataHtml = wikiHtml:tag( 'time' )
			:wikitext( wikiTexto )
	if wikiTexto:match( ' ' ) then
		dataHtml:addClass( 'nowrap' )
	end
	if isoTexto ~= wikiTexto then
		dataHtml:attr( 'datetime', isoTexto )
	end
	if not args.nolinks then
		dataHtml:addClass( 'dâta-lim' )
	end
	if nessence then 
		dataHtml:addClass( 'bday' )
	elseif mort then
		dataHtml:addClass( 'dday' )
	end
	
	wikiHtml:wikitext( jelien4 )
	
	if ajo then
		wikiHtml:wikitext( ' ' )
				:tag( 'span' )
					:addClass( 'noprint')
					:wikitext( ajo )
					:done()
	end
	
	return tostring( wikiHtml )
end


---
-- fonction destinée aux infobox, notamment pour afficher les dates de naissance et de mort
-- les liens présent dans les dates fournies sont automatiquement supprimées pour gérer les cas ou 
-- le paramètre contient déjà un modèle date.
-- Paramètres :
-- 		1 : type de date à afficher (naissance / n, mort / m, ou date / d)
-- 		1 : Date ou date de naissance
-- 		2 : Date de mort si type n ou m
-- 		qualificatif = suffixe des page de date à lier (exemple : en musique)
-- 		nolinks : n'affiche pas de lien
--		préfixe : préfixe à afficher s'il y a un jour (par défaut '')
--		préfixe sans jour : préfixe à afficher s'il n'y a pas de jour (par défaut : '')
function fun.dataEnfocajon( frame )
	local args = frame.args
	if type( args ) ~= 'table' or not ( args[1] and args[2] ) then
		return
	end
	
	-- analyseDate sépare la date du contenu qui suit, supprime les liens, et retourne si possible un table avec jour mois année
	local function analiseData( d )
		if trim( d ) then
			local analise = d:match( ' ou ben ') or d:match( 'entre-mié ' ) or d:match( 'de vers ' ) or d:match( 'aprés ' ) or d:match( 'devant ' )
			if analise then 
				return d
			end
			analise = d:match( 'datetime="([%d-]+)"' ) or d
			-- sépare la date (avec ses liens) d'une référence ou contenu commençant par un espace)
			local comencement, fin = analise:match( '(.-%d%d%d%]*%-?)([\127 ].+)' )
			if not comencement then
				-- sépare la date du contenu commençant par <br>
				comencement, fin = analise:match( '(.-%d%d%d%]*%-?)(<br ?/?>.+)' )
			end
			analise = comencement or analise
			-- supprime les lien
			analise = analise:gsub(
				'%[%[([^%[%]|]*)|?([^%[%]]*)%]%]',
				function ( l, t )
					return trim( t ) or l
				end
			)
			local t, r = fun.separacionJornMesAn( analise )
			if t then
				return r, fin
			else
				return d, fin
			end
		end
	end
	-- prefix ajoute un préfixe en fonction de la présence ou non du jour si le paramètre "préfixe sans jour" est défini
	local function prefix( dateString )
		if dateString then
			local datetime = dateString:match( 'datetime="([U%d%-]+)"' )
			if datetime and datetime:match('%-%d%d%-%d%d') and trim( args['prèfixo'] ) then
				return args['prèfixo'] .. ' ' .. dateString
			end
			if trim( args['prèfixo sen jorn'] ) then
				return args['prèfixo sen jorn'] .. ' ' .. dateString
			end
		end
		return dateString
	end
	
	local nessence = args[1]:match( '^n' ) == 'n'
	local mort = args[1]:match( '^m' ) or args[1]:match( 'môrt' )
	local viuaData, qualificatif = args[2], args[4]
	local viuaDataTab, resultatData, complementData
	local dataNessence, dataMort
	if mort then
		viuaData = args[3]
	end
	if not trim( viuaData ) then
		return
	end
	if viuaData:match( '</time>' ) then
		-- S'il y a des liens il y a probablement déjà un modèle date, évitons de l'exècuter une 2e fois
		if ( nessence or mort ) and ( viuaData:match( 'wikidata%-linkback' ))  then
			dataNessence = analiseData( args[2] )
			dataMort = analiseData( args[3] )
			resultatData = viuaData
		else 
			return prefix( viuaData )
		end
	else
		viuaDataTab, complementData = analiseData( viuaData )
		if type( viuaDataTab ) ~= 'table' then 
			return viuaDataTab
		else
			if nessence then
				dataNessence = viuaDataTab
				dataMort = analiseData( args[3] )
			elseif mort then
				dataNessence = analiseData( args[2] )
				dataMort = viuaDataTab
			else
				qualificatif = args[3]
			end
			viuaDataTab.nessence = nessence
			viuaDataTab.mort = mort
			viuaDataTab.qualificatif = args.qualificatif or qualificatif
			viuaDataTab.nolinks = args.nolinks
			viuaDataTab.nocat = args.nocat
			viuaDataTab.jelien = args.jelien
		end
	end
	resultatData = resultatData or fun.modeloData( viuaDataTab )
	
	local ajo, prefixAjo, suffixAjo, calculAjo = '', ' <span class="noprint">(', ')</span>', nil
	if nessence and
		dataNessence and
		not dataMort and
		type( dataNessence ) == 'table'
	then
		calculAjo = fun.ajo( dataNessence.an, dataNessence.numMes, dataNessence.jorn )
		if calculAjo and calculAjo > 120 then
			calculAjo = nil
		end
	elseif mort and
		dataNessence and
		dataMort and
		type( dataNessence ) == 'table'
		and type( dataMort ) == 'table'
	then
		calculAjo = fun.ajo(
			dataNessence.an,
			dataNessence.numMes,
			dataNessence.jorn,
			dataMort.an,
			dataMort.numMes,
			dataMort.jorn
		)
		prefixAjo = ' (tant qu’a '
		suffixAjo = ')'
	end
	if tonumber( calculAjo ) then
		if calculAjo > 1 then
			ajo = prefixAjo .. calculAjo .. '&nbsp;ans' .. suffixAjo
		elseif calculAjo == 1 then
			ajo = prefixAjo .. 'un&nbsp;an' .. suffixAjo
		elseif calculAjo == 0 then
			ajo = prefixAjo .. 'muens d’un&nbsp;an' .. suffixAjo
		end
		if complementData and complementData:match( 'ans?%)' ) then
			complementData = ''
		end
	end
	
	return prefix( resultatData ) .. ( complementData or '' ) .. ajo
end


---
-- la fonction dateISO renvoie un date au format aaaa-mm-jj (sans liens)
-- l'année peut être sous la forme 2013 ou [[2013 en litérature|2013]]
-- le mois peut être en lettre ou en chiffres
-- le jour peut être sous la forme '05', '{{1er}}' ou 'vendredi 13'
function fun.dataISO( frame )
	local args = Outils.extractArgs( frame )
	local an = Outils.notEmpty( args['an'], args.an, args.year, args.date )
	-- extraction de l'année
	if type( an ) == 'string' then
		an = ( tonumber( an )	-- match '2013'
				or string.match ( an, '%D(%d%d%d%d)%D' ) -- match  '[[2013 en musique|2013]]'
				or string.match ( an, '%D(%d%d%d%d)$' )  -- match '17 septembre 2013'
				or string.match ( an, '^(%d%d%d%d)%D' )  -- match '2013-09-17'
		)
	end
	an = tonumber( an )
	
	-- le format de date iso est défini suivant le calendrier grégorien.
	-- Avant l'année 1583 la date est calendrier est probablement du calendrier julien,
	-- donc autant s'abstenir.
	if an and an > 1582  then
		local mes = Outils.notEmpty( args.mes, args.month )
		-- num mois trouve le numéro du mois, qu'il soit numérique ou texte, complet ou abrégé.
		local nomMes, numMes = fun.determinacionMes( mes )
		if numMes then
			mes = '-' .. string.sub( '0' .. numMes, -2 )
			
			local jorn = Outils.notEmpty( args.jorn, args.day, args['quantiémo'] )
			if type( jorn ) == 'string' then
				jorn = tonumber( jorn ) or tonumber( string.match ( jorn, '%d+') )
			end
			jorn = tonumber( jorn )
			if jorn and jorn <= listaMes[numMes].nJorn then
				jorn = '-' .. string.sub( '0' .. jorn, -2 )
				return an .. mes .. jorn
			else
				return an .. mes
			end
		else
			return tostring( an )
		end
	end
end

---
-- Rang du jour dans l'année
-- Usage : do_dayRank{année,mois,jour}
function fun.do_dayRank(arguments)
	local yr = tonumber(arguments.year or arguments[1]) or 1
	local mt = tonumber(arguments.month or arguments[2]) or 1
	local dy = tonumber(arguments.day or arguments[3]) or 1
	-- Rangs des premiers des mois
	local ranks = {0,31,59,90,120,151,181,212,243,273,304,334}
	
	local rank = (ranks[mt] or 0) + dy - 1
	if(fun.isLeapYear(yr) and (mt >= 3)) then
		rank = rank+1
	end
	return rank
end

-- Nombre de jours entre deux années (du 1er janvier au 1er janvier)
-- Suit le calendrier grégorien
function fun.do_daysBetween(arguments)
	local yr1 = tonumber(arguments[1]) or 0
	local yr2 = tonumber(arguments[2]) or 0
	
	return fun.daysSinceOrigin(yr2) - fun.daysSinceOrigin(yr1)
end

-- Nombre de jours depuis l'année 1 (du 1er janvier au 1er janvier)
function fun.daysSinceOrigin(year)
	local yr = year-1
	return 365*yr + math.floor(yr/4) - math.floor(yr/100) + math.floor(yr/400)
end

-- Test d'année bissextile (Suit le calendrier grégorien)
function fun.isLeapYear(year)
	local yr = tonumber(year) or 1
	return (yr%4 == 0) and ((yr%100 ~= 0) or (yr%400 == 0))
end

-- Conversion d'un nombre en chiffres romains
function fun.toRoman(number)
	local n = math.floor(number)
	local letters = {"I","V","X","L","C","D","M","",""}
	local pattern = {"","0","00","000","01","1","10","100","1000","02"}
	local result = ""
	if(n<=0 or n>=4000) then
		result = "---"
	else
		for i=1,7,2 do
			local p = pattern[n%10 + 1]
			for j=0,2 do
				p = string.gsub(p,tostring(j),letters[i+j])
			end
			result = p .. result
			n = math.floor(n/10)
		end
	end
	return result
end

-- Conversion et affichage d'une date dans le calendrier républicain
function fun.dataRepubliquen(frame)
	local pframe = frame:getParent()
	local arguments = pframe.args
	return fun.formatRepCal(fun.do_toRepCal(arguments))
end

---
-- Calcul d'une date dans le calendrier républicain
-- On suppose que les années 4n+3 sont sextiles (3, 7, 11...)
function fun.do_toRepCal(arguments)
	local yr = tonumber(arguments.year or arguments[1]) or 2000
	-- rang absolu du jour demandé, le jour 0 étant le 22 septembre 1792 (1er jour de l'an I)
	local repDays = fun.do_dayRank(arguments) + fun.do_daysBetween{1792,yr} - fun.do_dayRank{1792,9,22}
	local repYear = math.floor((repDays+731)/365.25) - 1
	local repDayRank = repDays - 365*(repYear-1) - math.floor(repYear/4)
	local repMonth, repDay = math.floor(repDayRank/30)+1, (repDayRank%30)+1
	return {repYear, repMonth, repDay}
end

---
-- Formatage d'une date selon le calendrier républicain
-- Usage : fun.formatRepCal{année,mois,jour}
function fun.formatRepCal(arguments)
	local months = {"Vendèmiéro","Brumèro","Fremèro","Nevôso","Ploviôso","Ventôso","Gèrniâl","Flloriâl","Prâriâl","Mêssidor","Tèrmidor","Frutidor"}
	local extras = {"de la vèrtu","du g·enie","de l’ôvra","de les rècompenses","de l’avis","de la rebênâda"}
	local result = ""
	if(arguments[2] < 13) then
		result = result .. tostring(arguments[3]) .. "&nbsp;" .. months[arguments[2]]
	else
		result = result .. "jorn " .. extras[arguments[3]]
	end
	result = result .. " de l’an " .. fun.toRoman(arguments[1])
	return result
end

---
-- Voir Modèle:Âge
-- retourne l'age en fonction de la ou les dates fournies. La valeur retounée est de type 'number'
-- Parammètres :
-- 1, 2, 3 : année, mois jour de naissance (supposé dans le calendrier grégorien)
-- 4, 5, 6 : année, mois, joue du calcul (facultatif, par défaut la date UTC courante).
function fun.ajo( an, mn, jn, ac, mc, jc )
	if ac == nil then
		local today = os.date( '!*t' )
		ac = today.year
		mc = today.month
		jc = today.day
	else
		ac = tonumber( ac )
		mc = tonumber( mc )
		jc = tonumber( jc )
	end

	local ann = tonumber( ann )
	local mn = tonumber( mn )
	local jn = tonumber( jn )

	if ann == nil or ac == nil or mn == nil or mc == nil then
		-- pas de message d'erreur qui risque de faire planter la fonction appelante
		-- à elle de gérer ce retour.
		return
	end
	
	local ajo = ac - an
	if mc == mn then
		if jc == nil or jn == nil then
			return
		end
		return ajo-tonumber( jc < jn and 1 or 0 )
	else
		return ajo-tonumber( mc < mn and 1 or 0 )
	end
end

function fun.modeloAjo( frame )
	local args = frame.getParent().args
	local ajo = fun.ajo (
		args[1] or args['an'],
		args[2] or args['mês'],
		args[3] or args['jorn'],
		args[4],
		args[5],
		args[6]
	)
	if ajo then
		return ajo
	else
		return '<span class="error">Paramètros fôx ou ben ensufisents por calcular l’âjo justo</span>'
	end
end

---
-- calcul du jour julien à partir d'une date du calendrier grégorien
function fun.julianDay( year, month, day, hour, min, sec )
	local julian
	julian = math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) * 1461 / 4 )
			- math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) / 100 )
			+ math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) / 400 )
			+ math.floor( ( math.fmod( month + 57609, 12 ) + 4 ) * 153 / 5 )
			+ day + ( hour or 12 ) / 24 + ( min or 0 ) / 1440 + ( sec or 0 ) / 86400
			- 32167.5
	return julian
end

---
-- calcul du jour julien à partir d'une date du calendrier julien
function fun.julianDayJulian( year, month, day, hour, min, sec )
	local julian
	julian = math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) * 1461 / 4 )
			+ math.floor( ( math.fmod( month + 57609, 12 ) + 4 ) * 153 / 5 )
			+ day + ( hour or 12 ) / 24 + ( min or 0 ) / 1440 + ( sec or 0 ) / 86400
			- 32205.5
	return julian
end

---
-- calcul d'une date dans le calendrier grégorien à partir du jour julien
function fun.julianDayToGregorian( julianDay )
	local base = math.floor( julianDay + 32044.5 )  -- 1 March -4800 (proleptic Gregorian date)
	local nCentury = math.floor( ( base * 4 + 3 ) / 146097 )
	local sinceCentury = base - math.floor( nCentury * 146097 / 4 )
	local nYear = math.floor( ( sinceCentury * 4 + 3 ) / 1461 )
	local sinceYear = sinceCentury - math.floor( nYear * 1461 / 4 )
	local nMonth = math.floor( ( sinceYear * 5 + 2 ) / 153 )
	
	local day = sinceYear - math.floor( (  nMonth  * 153 + 2 ) / 5 ) + 1
	local month = nMonth  - math.floor(  nMonth  / 10 ) * 12 + 3
	local year = math.floor( sinceYear / 306 ) + nYear + 100 * nCentury - 4800
	
	return year, month, day
end

---
-- calcul d'une date dans le calendrier julien à partir du jour julien
-- calcul basé sur l'algorythme de la page fr.wikipedia.org/wiki/Jour_julien (1/10/2013)
function fun.julianDayToJulian( julianDay )
	local year = math.modf( ( julianDay * 4 - 6884469 ) / 1461 )
	local r2 = julianDay - math.modf( ( 1461 * year + 6884472 ) / 4 )
	local month = math.modf( ( 5 * r2 + 461 ) / 153 )
	local day = r2 - math.modf( ( 153 * month - 457 ) / 5 ) + 1
	if month > 12 then
		year = year + 1
		month = month - 12
	end
	return year, month, day
end

---
-- calcul d'une date dans le calendrier grégorien à partir d'une date dans le calendrier julien
function fun.julianToGregorian( year, month, day )
	return fun.julianDayToGregorian( fun.julianDayJulian( year, month, day ) )
end

---
-- calcul d'une date dans le calendrier julien à partir d'une date dans le calendrier grégorien
function fun.gregorianToJulian( year, month, day )
	year = tonumber(year)
	if month then month = tonumber(month) else month = 6 end --prend une valeur centrale pour donner un best "guess"
	if day then day = tonumber(day) else day = 15 end
	return fun.julianDayToJulian( fun.julianDay( year, month, day ) )
end



---
-- erreurModuleData affiche  d'un message d'erreur si le Module:Langue/Data n'a pas été chargé correctement,
-- pour la page de discussion de la base de donnée et ceux qui veulent surveiller cette page.
function fun.fotaModuloData()
	local success, resultat = pcall ( mw.loadData, 'Module:Dâta/Data' )
	if success == false then
		local message = [[<strong class="error">Lo chargement du modulo Dâta/Data balye na fôta : </strong><br />%s<br />

<span class="error">Cela fôta dêt étre corregiêe d’abôrd, de milyérs de pâge sè fant vêre pas coment fôt.</span>
]]
		return string.format( message, resultat )
	end
end

---
-- checkDataCat génère des liens vers les pages annuelles, mensuelles et d'éphémérides liè aux
-- catégories du Module:Date/Data. La date la plus ancienne dépend de 'aucun' et 'seul[1]'
-- Paramètres :
-- 	1 : la catégorie. Il y aura une section par qualificatif de cette catégorie.
-- 	mois : oui pour avoir les liens vers les pages mensuelles et éphémérides (4 jours dans l'année)
-- 	alias : pour avoir des lien pour les alias en plus des qualificatif
function fun.checkDataCat( frame )
	local category = trim(frame.args[1])
	local monthLinks = frame .args.mes == 'ouè'
	local alias = frame.args.alias == 'ouè'
	local dataLink = mw.loadData( 'Module:Dâta/Data' )
	local wikiList =  {}
	local currentYear = tonumber( os.date( '%Y' ) )
	local columns = '<div style="-moz-column-width:5em;-webkit-column-width:5em;column-width:5em;-moz-column-gap:1em;-webkit-column-gap:1em;column-gap:1em;text-align:left;">'
	local newSection
	if monthLinks then
		newSection = '\n\n== %s ==\n\n=== Ans ===\n' .. columns
	else
		newSection ='\n\n== %s ==\n' .. columns
	end
	for field, dataField in pairs( dataLink ) do
		-- boucle sur tous les qualificatif ayant pour catégorie le premier paramère
		if dataField.cat == category or ( category == 'cat' and dataField.cat == field ) then
			local monthInitialYear, initialYear
			-- définition de l'année à partir de laquelle on va tester toutes les année / mois
			if dataField.qualificatif == field or ( category == 'cat' and dataField.cat == field ) then
				if dataField.an and dataField.an.nion and dataField.an.nion < currentYear then
					local nion = ( dataField.an.solet and dataField.an.solet[1] ) or dataField.an.nion
					initialYear = math.min( nion - math.ceil( (currentYear - nion) / 4 ), currentYear - 50 )
				else
					initialYear = currentYear - 50
				end
				if dataField.mes and tonumber( dataField.mes.nion ) and ( tonumber( dataField.mes.nion ) < currentYear ) then
					local nion = dataField.mes.nion
					monthInitialYear = math.min( nion - math.ceil( (currentYear - nion) / 4 ), currentYear - 8 )
				else
					monthInitialYear = currentYear - 8
				end
			elseif alias then
				-- si le paramètre alias est défini on teste aussi tous les alias, sinon ils sont ignorés
				initialYear = currentYear - 50
				monthInitialYear = currentYear - 8
			end
			
			-- création de l'ensembles des liens
			if initialYear then
				-- ajout de lien vers les pages annuelles de l'année en court + 5 jusqu'à initialYear
				table.insert( wikiList,  string.format( newSection, field ) )
				local fieldLink = ' ' .. field
				if category == 'cat' then
					fieldLink = ' ' .. dataField.qualificatif
				end
				for year = ( currentYear + 5 ), initialYear, -1  do
					table.insert( wikiList,  '\n* [[' .. year .. fieldLink ..'|' .. year .. ']]' )
				end
				table.insert( wikiList,  '\n</div>' )
				
				if monthLinks then
					-- insertstion de liens vers les mois de l'année en court + 1 jusqu'à monthInitialYear
					table.insert( wikiList,  '\n\n=== Mois ==='  )
					local month, sep
					for year = ( currentYear + 1 ), monthInitialYear, -1  do
						table.insert( wikiList,  '\n* ' .. year .. ' : ' )
						sep = ' • '
						for j = 1, 12 do
							month = ucfirst( listaMes[j].nom ) .. ' '
							if j == 12 then sep = ''
							end
							table.insert( wikiList,  '[[' .. month .. year .. ' ' .. fieldLink .. '|' .. month .. ']]' .. sep )
						end
					end
					
					-- insertion de quelques date pour tester les éphémérides
					table.insert( wikiList,  '\n\n=== Jorns ==='  )
					table.insert( wikiList,  '\n* [[1ér de janviér ' .. fieldLink .. ']]' )
					table.insert( wikiList,  '\n* [[14 de mârs ' .. fieldLink .. ']]' )
					table.insert( wikiList,  '\n* [[22 de jouin ' .. fieldLink .. ']]' )
					table.insert( wikiList,  '\n* [[3 de septembro ' .. fieldLink .. ']]' )
				end
			end
		end
	end
	
	return table.concat( wikiList )
end

--[[
  Cette fonction retourne "CET" ou "CEST" selon que dans la pseudo-timezone en cours
    c'est l'heure d'été ou l'heure d'hiver.
  Cette fonction n'a de sens a priori que pour des modèles utilisés en Europe
  
  Paramètre optionnel non nommé : "sans lien" : retourne le texte CET/CEST. sinon
    retourne ce même texte avec un wikilien vers les articles correspondant
--]]
function fun.CEST(frame)
	-- option : ne pas créer de wikilien
	local opt = trim(frame.args[1] or frame:getParent().args[1])
	-- on récupère l'information dans la zone courante
	local t = mw.getContentLanguage():formatData("I", nil, true)
	
	if (t == "1") then  -- heure d'été
		if (opt == "sen lim") then
			return "CEST"
		elseif (opt == "dècalâjo") then
			return "2"
		else
			return "[[Hora de chôd-temps d’Eropa centrâla|CEST]]"
		end
	else  -- heure d'hiver (ou autre zone où ça ne s'applique pas)
		if (opt == "sen lim") then
			return "CET"
		elseif (opt == "dècalâjo") then
			return "1"
		else
			return "[[Hora normala d’Eropa centrâla|CET]]"
		end
	end
end

return fun