Ouvrir le menu principal

Module:Date républicaine

Révision datée du 13 mai 2020 à 15:12 par Yves.bertin (discussion | contributions) (Page créée avec « local p = {} local Outils = require( 'Module:Outils' ) local trim = Outils.trim local OutilsDates = require( 'Module:Date' ) local modeleDate = OutilsDates.modeleDate loc… »)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)

Le module date républicaine permet la mise en forme de dates du calendrier républicain. Il est lié aux modèles {{date républicaine}} et {{date républicaine-}}.

Utilisation

Fonctions utilisables depuis un modèle

  • date_republicaine(frame) – renvoie une chaîne de caractères présentant une date du calendrier républicain avec les liens les plus pertinents en respectant les conventions typographiques, et éventuellement la date du calendrier républicain correspondante.
  • date_republicaine_sans_liens(frame) – renvoie une chaîne de caractères présentant une date du calendrier républicain en respectant les conventions typographiques, et éventuellement la date du calendrier républicain correspondante.

Fonctions utilisables depuis un autre module

  • conversion_Gregorien(jour, mois, an) – renvoie les jours, mois et années dans le calendrier républicain à partir des jour, mois et année dans le calendrier grégorien.
  • _date_republicaine(liens, {a1, a2, a3, a4}) – renvoie une chaîne de caractères présentant une date du calendrier républicain avec les liens les plus pertinents en respectant les convention typographiques (en paramètres : un booléen indiquant s'il faut faire des liens, et un table contenant une chaine de caractères avec une date du calendrier républicain en extension (« jour mois année », ou une chaîne de caractère par élément (« jour », « mois », « année »)).

Autres fonctions

  • extraction_argument (argument, chaine) – extrait de « argument » une chaine de caractère correspondant au pattern « chaine » ainsi que des informations sur le mode d'affichage de l'élément (suivi de « - » : ne pas afficher ; suivi de « * », ne pas présenter de lien wiki pour cet élément), et renvoie argument délesté de cette chaîne.
  • test_argument (argument) – analyse les paramètres fournis à la fonction _date républicaine(frame)
  • annee_affichee(annee, lien_annee, libelle_an) – mise en forme de l'année (liens et typographie) composant une date du calendrier républicain.
  • categorie_erreur (message) – mise en forme d'un message d'erreur avec insertion d'une catégorie de maintenance.

Modules externes dont ce module a besoin pour fonctionner

Fonctionnement

La mise en forme et le paramétrage ont été définis en fonction des conventions typographiques et de l'usage de présentation des dates dans les articles.

Le frame reçu peut se présenter sous deux formes :

  • avec séparateurs : {{date républicaine|jour|mois|année|(paramètre conversion optionnel)}} ;
  • sans séparateurs : {{date républicaine|jour mois année|(paramètre conversion optionnel)}}.

Le module analyse crée une chaîne concaténant tous les paramètres qui ne contiennent pas « conversion ». Il est nécessaire que :

  • l'année, si elle est fournie, soit en chiffres romains ; elle peut être précédée de « an » ou « de l'an », avec ou sans majuscule, les deux apostrophes sont acceptées ;
  • l'orthographe du mois, si il est fourni, soit exacte aux accents près ;
  • le jour, s'il est fourni, soit numérique.

Les liens créés suivent la même logique que le modèle date :

  • pour le jour : [[jour mois]], sinon pas de lien ;
  • pour le mois : [[mois année]], sinon [[mois]] (tous les mois ont un article) ;
  • pour l'année : [[année]] (toutes les années ont un article).

Accessibilité :

  • les nombres en chiffres romains sont dotés d'une infobulle donnant leur valeur en chiffres arabes.

Typographie :

  • les éléments sont séparés par des espaces insécables ;
  • les mois et année sont affichés avec une minuscule, sauf dans le cas où ils sont les premiers éléments de la chaîne de caractère renvoyée, auquel cas la casse retenue est celle fournie en entrée (cas où le mois ou l'année sont au début d'une phrase) ;
  • le choix de l'apostrophe est laissé au rédacteur, le module restitue celle fournie en entrée.

Mode de sélection des éléments affichés :

  • comme pour le module Date, la mention d'un « - » accolé à un élément permet d'en éviter l'affichage ;
  • la mention d'un « * » accolé à un élément permet d'éviter l'affichage d'un lien pour cet élément (inutile pour le module Date_republicaine_sans_lien, mais ne provoque pas d'erreur).

Paramètre de conversion en date grégorienne (passage d'un élément contenant « conversion » ou « grégorien ») :

  • séparateur :
    • par défaut, la présentation est de la forme « jj mois an NN (jj mois an) »,
    • en précisant « : » (« conversion: » ou « grégorien: »), la présentation est de la forme « jj mois an NN : jj mois an » ;
  • affichage ou non des liens :
    • sa mention simple permet l'affichage de la date grégorienne correspondante entre parenthèses, avec les liens (équivalent du modèle {{date}}),
    • sa mention avec « * » fait la même chose sans liens (équivalent du modèle {{date-}}) ;
  • sélection des éléments à afficher :
    • l'ajout d'une combinaison des lettres j, m et a (j : jour, m : mois, a : année) permet de sélectionner les éléments de la date grégorienne à afficher. Sans précision ou en précisant « jma » tout est affiché, en précisant « jm » seul le jour et le mois sont affichés, etc.

Exemples

Pour plus d'exemples, voir les pages de test des modèles date républicaine et date républicaine- permettant d'évaluer les modifications apportées.

  • {{#invoke:Date républicaine|date_republicaine|1er vendémiaire an II}}1er vendémiaire an II
  • {{#invoke:Date républicaine|date_republicaine|1er vendémiaire de l’an II}}1er vendémiaire de l’an II
  • {{#invoke:Date républicaine|date_republicaine_sans_liens|1er vendémiaire an II}}1er vendémiaire an II
  • {{#invoke:Date républicaine|date_republicaine|2 vendémiaire an II}}2 vendémiaire an II
  • {{#invoke:Date républicaine|date_republicaine|2 vendémiaire an III}}2 vendémiaire an III
  • {{#invoke:Date républicaine|date_republicaine|Vendémiaire an III}}Vendémiaire an III
  • {{#invoke:Date républicaine|date_republicaine|An III}}An III
  • {{#invoke:Date républicaine|date_republicaine|1er vendémiaire* an II}}1er vendémiaire an II
  • {{#invoke:Date républicaine|date_republicaine|1er vendémiaire an II-}}1er vendémiaire
  • {{#invoke:Date républicaine|date_republicaine|1er vendémiaire an II|grégorien}}1er vendémiaire an II ()
  • {{#invoke:Date républicaine|date_republicaine|1er vendémiaire an II|grégorien*}}1er vendémiaire an II ()
  • {{#invoke:Date républicaine|date_republicaine|1er vendémiaire an II|grégorien:}}1er vendémiaire an II :
  • {{#invoke:Date républicaine|date_republicaine|1er vendémiaire an II|grégorien jm}}1er vendémiaire an II ()

local p = {}
local Outils = require( 'Module:Outils' )
local trim = Outils.trim
local OutilsDates = require( 'Module:Date' )
local modeleDate = OutilsDates.modeleDate

local type_romains = "[IVXL]+"
local type_nombre = "[0-9]+"
local type_1er = "1er"
local type_jour_complementaire = "[1-6]e%*?%-? [Jj]our compl[eé]mentaire"

-- Table des libellés à afficher pour 1er, 2e, 3e, 4e, 5e, 6e
local infobulle = {
	["1er"] = "Premier",
	["2e"] = "Deuxième",
	["3e"] = "Troisième",
	["4e"] = "Quatrième",
	["5e"] = "Cinquième",
	["6e"] = "Sixième"
}

-- Table des noms des mois républicains, avec la casse de la première lettre et les erreurs acceptables
local listeNomsMois = {
	{"vendémiaire", "vendémiaire"},
	{"vendemiaire", "vendémiaire"},
	{"Vendémiaire", "vendémiaire"},
	{"Vendemiaire", "vendémiaire"},
    {"brumaire", "brumaire"},
    {"Brumaire", "brumaire"},
    {"frimaire", "frimaire"},
    {"Frimaire", "frimaire"},
    {"nivôse", "nivôse"},
    {"nivose", "nivôse"},
    {"Nivôse", "nivôse"},
    {"Nivose", "nivôse"},
    {"pluviôse", "pluviôse"},
    {"pluviose", "pluviôse"},
    {"Pluviôse", "pluviôse"},
    {"Pluviose", "Pluviôse"},
    {"ventôse", "ventôse"},
    {"ventose", "ventôse"},
    {"Ventôse", "ventôse"},
    {"Ventose", "ventôse"},
    {"germinal", "germinal"},
    {"Germinal", "germinal"},
    {"floréal", "floréal"},
    {"floreal", "floréal"},
    {"Floréal", "floréal"},
    {"Floreal", "floréal"},
    {"prairial", "prairial"},
    {"Prairial", "prairial"},
    {"messidor", "messidor"},
    {"Messidor", "messidor"},
    {"thermidor", "thermidor"},
    {"Thermidor", "thermidor"},
    {"fructidor", "fructidor"},
    {"Fructidor", "fructidor"},
    {"jour complémentaire", "jour complémentaire"},
    {"jour complementaire", "jour complémentaire"},
    {"Jour complémentaire", "jour complémentaire"},
    {"Jour complementaire", "jour complémentaire"}
}

-- Table des noms des mois républicains, avec la casse de la première lettre et les erreurs acceptables
local listeOrdreMois = {
	["vendémiaire"] = 1,
    ["brumaire"] = 2,
    ["frimaire"] = 3,
    ["nivôse"] = 4,
    ["pluviôse"] = 5,
    ["ventôse"] = 6,
    ["germinal"] = 7,
    ["floréal"] = 8,
    ["prairial"] =9,
    ["messidor"] = 10,
    ["thermidor"] = 11,
    ["fructidor"] = 12,
    ["jour complémentaire"] = 13
}

-- Liste des jours complémentaires
local listeJoursComplementaires = {
	{"jour de la vertu", 1},
	{"Jour de la vertu", 1},
    {"jour du génie", 2},
    {"Jour du génie", 2},
    {"jour du travail", 3},
    {"Jour du travail", 3},
    {"jour de l'opinion", 4},
    {"Jour de l'opinion", 4},
    {"jour des récompenses", 5},
    {"Jour des récompenses", 5},
    {"jour de la Révolution", 6},
    {"Jour de la Révolution", 6},
    {"jour de la révolution", 6},
    {"Jour de la révolution", 6}
}

-- Table temporaire pour éviter les requêtes de test d'existence des articles.
-- Liste des articles existants sur les jours/mois, à remplacer par un table externe
local listeArticlesJours = {
	["1er vendémiaire"] = true,
    ["7 vendémiaire"] = true,
    ["13 vendémiaire"] = true,
    ["14 vendémiaire"] = true,
    ["15 vendémiaire"] = true,
    ["16 vendémiaire"] = true,
    ["17 vendémiaire"] = true,
    ["18 vendémiaire"] = true,
    ["19 vendémiaire"] = true,
    ["20 vendémiaire"] = true,
    
    ["18 brumaire"] = true,
    ["19 brumaire"] = true,
    ["20 brumaire"] = true,
    ["21 brumaire"] = true,
    ["22 brumaire"] = true,
    ["12 brumaire"] = true,
    ["23 brumaire"] = true,
    ["24 brumaire"] = true,
    
    ["4 frimaire"] = true,
    ["10 frimaire"] = true,
    ["11 frimaire"] = true,
    
    ["25 nivôse"] = true,
    ["13 nivôse"] = true,
    
    ["13 pluviôse"] = true,
    ["16 pluviôse"] = true,
    
    ["19 ventôse"] = true,
    
    ["16 germinal"] = true,
    ["11 germinal"] = true,
    
    ["10 floréal"] = true,
    
    ["25 prairial"] = true,
    ["30 prairial"] = true,
    
    ["8 messidor"] = true,
    ["23 messidor"] = true,
    ["30 messidor"] = true,
    
    ["9 thermidor"] = true,
    
    ["18 fructidor"] = true,
    ["20 fructidor"] = true,
    ["30 fructidor"] = true,
    ["6 fructidor"] = true
}

-- Table temporaire pour éviter les requêtes de test d'existence des articles.
-- Liste des articles existants sur les mois/année, à remplacer par un table externe
local listeArticlesMois = {
    ["floréal an LXXIX"] = true,
    ["prairial an LXXIX"] = true,
	["vendémiaire an II"] = true
}
   
-- liste des chiffres romains pour contrôle mise en forme de l'infobulle
local listeRomains = {	["I"] = "1",
	["II"] = "2",
	["III"] = "3",
	["IV"] = "4",
	["V"] = "5",
	["VI"] = "6",
	["VII"] = "7",
	["VIII"] = "8",
	["IX"] = "9",
	["X"] = "10",
	["XI"] = "11", 
	["XII"] = "12",
	["XIII"] = "13",
	["XIV"] = "14",
	["LXXIX"] = "79"
}

-- extrait une chaîne de caractère (jour, mois ou année) du type passé en paramètre (string ou pattern),
-- en restituant :
-- § la chaîne exacte obtenue
-- § l'argument de départ délesté de cette chaîne
-- § un booléen indiquant la présence d'un indicateur d'affichage de l'éléments (-)
-- § un booléen indiquant la présence d'un indicateur de mise en place d'un lien sur l'élément (*)
function p.extraction_argument (argument, chaine)
	local x, position = 0, 0
	local lien, afficher = true, true
	local extrait = ''
	local chaine2 = ''
 	position = mw.ustring.find (argument, chaine)
 	if position	then
 		chaine2 = mw.ustring.match(argument, chaine)
	  	x = position + mw.ustring.len(chaine2)
		if x < (mw.ustring.len(argument) + 1) then
			if mw.ustring.sub(argument, x, x) == '*' then
				lien = false
				x=x+1
			else
				if mw.ustring.sub(argument, x, x) == '-' then
					afficher = false
					x=x+1
				end
			end
		end
		extrait = mw.ustring.sub(argument, position, x - 1)
		argument = mw.ustring.sub(argument, 1, position - 1)..mw.ustring.sub(argument, x)
	end
		
	return argument, extrait, afficher, lien
 end
 	
-- Extraction d'éventuels jour, mois et année du calendrier républicain.
--
-- Le paramètre en entrée est sous la forme d'une chaîne, le séparateur étant l'espace
-- l'année doit être en chiffres romains
-- "an" peut être omis devant l'année ;
--         si l'affichage de l'année seul est demandé, "an" sera omis également à l'affichage
--               Ce cas est utile pour les formes : ans I, II et III
-- sont acceptés : an, An, de l'an, de l'An, de l’an, de l’An
-- le jour doit être numérique, "er" est accepté pour le premier jour de chaque mois
-- les paramètres peuvent être présentés dans n'importe quel ordre
-- les mois doivent être orthographiés correctement, mais les accents peuvent être omis
-- La majuscule n'est prise en compte que pour les nots possiblement en début de phrase :
--   § le mois est affiché et il n'y a pas de numéro de jour devant
--   § l'année est affichée et il n'a a pas d'autre élément devant
function p.test_argument (argument)
	local tab = { test = true,
					message = '',
					quantieme = '',
					exposant_jour = '',
					test_quantieme = false,
					test_jour_complementaire = false,
					mois = '',
					test_mois = false,
					an = '',
					test_an = false,
					lien_jour = true,
					lien_mois = true,
					lien_an = true,
					afficher_jour = true,
					afficher_mois = true,
					afficher_an = true,
					jour_saisi = '',
					complementaire_saisi = '',
					mois_saisi = '',
					an_saisi = '',
					libelle_an = ''
					}
	local position = 0

-- On remplace les éventuels espaces insécables par des espaces simples pour simplifier le traitement qui suit
	argument = argument
		-- nbsp
		:gsub( '\194\160', ' ' )
		:gsub( '&nbsp;', ' ' )
		:gsub( '&#160;', ' ' )
		-- narrow nbsp
		:gsub( '\226\128\175', ' ' )
		:gsub( '&#8239;', ' ' )
		-- thin space
		:gsub( '\226\128\137', ' ' )
		:gsub( '&thinsp;', ' ' )
		:gsub( '&#8201;', ' ' )
		-- simple space
		:gsub( '&#32;', ' ' )
					
-- On retire l'éventuel "er" de "1er" pour simplifier le traitement qui suit
    if argument:match (type_1er) then
		argument=argument:gsub('1er', '1')
	end

-- On recherche si c'est sous la forme "6e jour complémentaire" pour écarter le "e"
	if mw.ustring.find(argument, type_jour_complementaire) then
		tab.exposant_jour = 'e'
		position = mw.ustring.find (argument, type_jour_complementaire)
		if position	then
			if position == 1 then
				argument=mw.ustring.sub(argument, 1, 1)..mw.ustring.sub(argument, 3)
			else
				argument=mw.ustring.sub(argument, 1, position)..mw.ustring.sub(argument, position + 2)
			end
		end
	end

-- On recherche le mois, s'il existe il est retiré de la chaîne de caractère analysée
	for _, nomMois in ipairs( listeNomsMois ) do
 		if mw.ustring.find (argument, nomMois[1]) then
 			argument, tab.mois_saisi, tab.afficher_mois, tab.lien_mois = p.extraction_argument (argument, nomMois[1])
			tab.mois = nomMois[2]
			tab.test_mois = true
  			break
 		end
	end

-- On recherche s'il s'agit d'un des six "jours complémentaires", si c'est le cas il est retiré de la chaîne de caractère analysée
-- On conserve le libellé du jour
	for _, jourComplementaire in ipairs( listeJoursComplementaires ) do
		if mw.ustring.find (argument, jourComplementaire[1]) then
 			argument, tab.complementaire_saisi, tab.afficher_jour, tab.lien_jour = p.extraction_argument (argument, jourComplementaire[1])
			tab.test_jour_complementaire = true
			tab.quantieme = tab.complementaire_saisi
			if not(tab.afficher_jour and tab.lien_jour) then
				tab.quantieme = mw.ustring.sub (tab.quantieme, 1, mw.ustring.len(tab.quantieme) - 1)
			end
			break
		end
	end
	
-- On recherche le jour en chiffres. Si on le trouve, il est retiré de la chaîne analysée
	if argument:match (type_nombre)	then
		tab.test_quantieme = true
		tab.quantieme = argument:match (type_nombre)
		if tab.quantieme == '1'	then
			tab.exposant_jour = 'er'
		end
		argument, tab.jour_saisi, tab.afficher_jour, tab.lien_jour = p.extraction_argument (argument, tab.quantieme)
		if (tonumber(tab.quantieme) < 1) or (tonumber(tab.quantieme) > 30) then
			tab.test = false
			tab.message = '<span class="error">le jour doit être compris entre 1 et 30 (' .. tab.quantieme .. ')</span>'
			return tab
		end
	end

-- Si la chaîne analysée est vide, le traitement est terminé 
 	argument=trim(argument)
	if argument	then
-- On extrait l'année, donc on "élimine" les formulations du type "an" ou "de l'an" pour
-- récupérer le numéro d'année en chiffres romains
		argument, tab.libelle_an = p.extraction_argument (argument, "de l[%'’][Aa]n")
		if tab.libelle_an == '' then
			argument, tab.libelle_an = p.extraction_argument (argument, 'An')
			if tab.libelle_an == '' then
				argument, tab.libelle_an = p.extraction_argument (argument, 'an')
			end
		else
			tab.libelle_an = mw.ustring.lower (tab.libelle_an)
		end
-- On vérifie si la chaîne qui reste est une année sous la forme "XX"
		if argument:match (type_romains) then
			tab.test_an = true
			tab.an = argument:match (type_romains)
			argument, tab.an_saisi, tab.afficher_an, tab.lien_an = p.extraction_argument (argument, tab.an)
		end

		if tab.test_an then
			if not listeRomains[tab.an]	then
				tab.test = false
				tab.message = '<span class="error">année hors du calendrier républicain (' .. tab.an .. ')</span>'
				return tab
			end
		end
		argument=trim(argument)
		if argument	then
-- La chaîne n'est pas sous un format attendu, message d'erreur
 			tab.test = false
 			tab.message = '<span class="error">format de date incorrect (' .. argument .. ')</span>'
 		end
	end
	return tab
end

-- Mise en forme de l'année affichée
-- § le paramètre année en entrée doit être sous la forme de chiffres romains
-- § le paramètre lien_annee indique si faut formater un lien vers un article de wikipédia
-- § le paramètre libelle_an indique le format de présentation : exemples : "de l'an", "An", etc.
function p.annee_affichee(annee, lien_annee, libelle_an)
	local chaine = ''
	local annee_affichee = ''
	local premier_car = ''
	local avant_an = ''
	local test = true
	local message = ''

	if annee then
-- Vérification de la syntaxe en chiffres romains
		if annee:match(type_romains) then
			if libelle_an then
-- gestion du cas des formats du type "de l'an" pour récupérer la typo (apostrophe) et éviter que
-- le lien porte sur autre chose que "an NN" pour donner "de l'[[an NN]]" et non pas "[[An NN|de l'an NN]]"
				if mw.ustring.sub(libelle_an, 1, 1) == 'd' then
				    annee_affichee = 'an '
  				    avant_an = mw.ustring.sub(libelle_an, 1, 5)
				else
					annee_affichee = libelle_an..' '
				end
			else
				annee_affichee = 'an '
			end
-- Récupération de la valeur affichée dans l'infobulle
			annee_affichee = annee_affichee..'<abbr class="abbr" title="'..listeRomains[annee]..'">'..annee..'</abbr>'
			if lien_annee then
-- Cas particulier de l'an I
				if annee == 'I'	then
					chaine = '[[An I du calendrier républicain|'..annee_affichee..']]'
				else
					chaine = '[[An '..annee..'|'..annee_affichee..']]'
				end
			else
				chaine = annee_affichee
			end
			chaine = avant_an..chaine
			return test, chaine
		end
	else
		test = false
		message = '<span class="error">aucune année passée en paramètre (annee_affichee)</span>'
		return test, message
	end
end

-- Fonction calculant une date du calendrier grégorien à partir d'une date du calendrier républicain
function p.conversion_Gregorien (jour, mois, an)
-- table du nombre de jour écoulé depuis le début de l'année jusqu'au premier de chaque mois du calendrier grégorien
-- (sans tenir compte des années bissextiles)
	local rang_mois_Greg = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }
	local x = 0
	local jour_Rep, mois_Rep, an_Rep, jour_Greg, mois_Greg, an_Greg = '', '', '', '', '', ''
	local test = true
	local message = ''

-- Fonction permettant de connaître le nombre de jours bissextiles entre deux années
    local function nb_jours_complement_bissextile (an)
    	local nb = 0
    	for i = 1792, 1791+an do
    		if  OutilsDates.isLeapYear(i) then
    			nb = nb + 1
    		end
    	end
    	return nb
    end
    
-- Si la date se présente sous la forme "nom de jour complémentaire an XX", on détermine le rang chronologique du jour en question 
	if (mois == 'jour complémentaire') and (jour:match('^[Jj]our')) then
		for _, jourComplementaire in ipairs( listeJoursComplementaires ) do
			if jourComplementaire[1] == jour then
				jour_Rep = jourComplementaire[2]
				break
			end
		end
	else
		jour_Rep = tonumber(jour)
	end

-- Valeurs numériques de l'année et du mois républicains				
	an_Rep = tonumber(listeRomains[an])
	mois_Rep = listeOrdreMois[mois]

-- contrôles ?
--	if not (an_Rep < 14) and not (mois_Rep < 4)
--	then
--		if not (an_Rep == 79)
--		then
--			return false, 'Pas de conversion pour les dates non officielles'
--		end
--	end
	
-- On détermine le nombre de jour entre la date transmise et le 1er janvier 1792. On connaît le nombre de jour entre le 1er janvier
-- et le 22 septembre 1792, première journée du calendrier républicain : 265
-- On multiplie le nombre d'années écoulées avant l'année en cours par 365, et on ajoute un jour par année sextile (pour les périodes considérées,
-- durant lesquelles ce calendrier a été officiel, tous les quatre ans à partir de l'an III).
-- On multiplie le nomdre de mois écoulés avant le mois en cours par 30
-- On ajoute le quantième du jour transmis ou calculé
	jour_Greg = 365*(an_Rep -1) + 30*(mois_Rep - 1) + jour_Rep + math.floor(an_Rep/4) + 265
	
-- On ajoute le résultat de la division de la partie entière du nombre de jours trouvé par la durée d'une année,
-- en tenant compte des années bissextiles comprises dans la période
	an_Greg = 1792 + math.floor((jour_Greg - nb_jours_complement_bissextile (an_Rep)-1)/365)
	
-- On calcule le reste de jours en tenant compte des années bissextiles
-- (une toutes les 4 ans sauf celles qui sont divisibles par 4 et par cent mais pas par 400)
	jour_Greg = jour_Greg - (an_Greg-1792)*365 - math.floor((an_Greg-1789)/4) + math.floor(an_Greg/1801) + math.floor(an_Greg/1901)
	
-- On détermine le mois correspondant au résultat
	local n = 1
	local m = 1
	local r = 0
	local bissextile = OutilsDates.isLeapYear(an_Greg)
	for i = 1, 12 do
		r = rang_mois_Greg[i]
-- Prise en compte d'un éventuel 29 février (années bissextiles, via isLeapYear(year) du module Date)
		if bissextile then
			if i > 2 then
				r = r + 1
			end
		end
		if not(r < jour_Greg) then
			i = 12
		else
			n = r
			m = i
		end
	end
	
	mois_Greg = m
	jour_Greg = jour_Greg - n
	
	return test, message, jour_Greg, mois_Greg, an_Greg

end

-- Contrôle et mise en forme
function p._date_republicaine (aucun_lien, args)
	local tab = { test = true,
					nocat = false,
					message = '',
					quantieme = '',
					exposant_jour = '',
					test_quantieme = false,
					test_jour_complementaire = false,
					mois = '',
					test_mois = false,
					an = '',
					test_an = false,
					lien_jour = true,
					lien_mois = true,
					lien_an = true,
					afficher_jour = true,
					afficher_mois = true,
					afficher_an = true,
					jour_saisi = '',
					complementaire_saisi = '',
					mois_saisi = '',
					an_saisi = '',
					libelle_an = ''
					}
	local test_conversion, test_conversion_sans_lien = false, false
	local conv_jour_mois, conv_jour, conv_an, conv_mois_an = false, false, false, false
	local deux_points = false
	local parametres, chaine = '', ''

-- Test pour ne pas catégoriser les pages indésirables dans les catégories spéciales de maintenance
	if args.nocat then
		if args.nocat == '' then
			tab.nocat = true
		end
	end
-- § Les paramètres peuvent se présenter sous la forme d'une seule chaîne ou de 3 paramètres séparés.
-- Dans ce dernier cas, on constitue une chaîne en utilisant l'espace comme séparateur, ce qui permet un traitement unique pour les 2 cas
-- § Si "conversion" ou "grégorien" est spécifié, on stocke l'info mais on ne l'inclut pas dans la chaîne ; il faut en plus
-- vérifier :
-- §§ si * est présisé (dans ce cas, pas de liens sur la date grégorienne convertie)
-- §§ si le caractère ":" apparaît, pour savoir si le séparateur est ":", sinon ce sont des parenthèes
-- §§ si une des séquences "jm", "j", "ma" ou "a" sont présentes, pour déterminer quels éléments de la date grégorienne
--           doivent être affiché (j=jour, m=mois, a=an)
	for i = 1, 4 do
		if args[i] then
			if (mw.ustring.match (args[i], '[Cc]onversion')) or (mw.ustring.match (args[i], '[Gg]régorien')) then
				if not mw.ustring.match (args[i], 'jma') then
					if mw.ustring.match (args[i], 'jm') then
						conv_jour_mois = true
					elseif mw.ustring.match (args[i], 'j') then
						conv_jour = true
					elseif mw.ustring.match (args[i], 'ma') then
						conv_mois_an = true
					elseif mw.ustring.match (args[i], 'a') then
						conv_an = true
					end
				end
				if mw.ustring.match (args[i], ':') then
					deux_points = true
				end
				if mw.ustring.match (args[i], '%*') then
					test_conversion_sans_liens = true
				else
					test_conversion = true
				end
			else
				parametres = parametres..args[i]..' '
			end
		end
	end

 	if parametres then
 		tab = p.test_argument (parametres)
 	else
 		tab.test = false
 		tab.message = p.categorie_erreur (tab.nocat, '<span class="error">Aucun paramètre transmis</span>')
 		return tab.message
 	end

-- Contrôle sur le nombre de jours si c'est un jour complémentaire
	if tab.mois and tab.quantieme then
		if (tab.mois == 'jour complémentaire') then
			if (tonumber(tab.quantieme) > 6) then
				tab.test = false
				tab.message = '<span class="error">Il n\'y a que 6 jours complémentaires au maximum (' .. tab.quantieme .. ')</span>'
			else
				if tab.an then
					if (tonumber(tab.quantieme) == 6) and not ((tab.an == 'III') or (tab.an == 'VII') or (tab.an == 'XI')) then
						tab.test = false
						tab.message = '<span class="error">Il n\'y a que 5 jours complémentaires cette année là (' .. tab.quantieme .. ')</span>'
					end
				end
			end
		end
	end
	
	if not tab.test	then
		tab.message = p.categorie_erreur (tab.nocat, tab.message)
		return tab.message
	end
	
	if aucun_lien then
		tab.lien_jour, tab.lien_mois, tab.lien_an = false, false, false
	end

-- Début de la mise en forme typographique et de l'établissement des liens possibles sur une date du calendrier républicain
-- le paramètre "date_affiche" reçoit les éléments au fur et à mesure de l'analyse
	local date_affichee = ''
	local jour = ''
	local jour_affiche = ''
	local article = ''

-- Si on a le jour mais pas le mois, c'est un cas invalide
	if tab.test_quantieme and not(tab.test_mois) then
		tab.message = p.categorie_erreur (tab.nocat, '<span class="error">date invalide, mois manquant</span>')
		return tab.message
 	else
-- on ne peut pas avoir en même temps un jour complémentaire et un numéro de jour ou un mois
		if (tab.test_quantieme or tab.test_mois) and tab.test_jour_complementaire then
			tab.test = false
			tab.message = p.categorie_erreur (tab.nocat, '<span class="error">date invalide, paramètres incompatibles</span>')
			return tab.message
		end
	end
	
-- Cas où l'année n'est pas spécifiée
	if not tab.test_an then
-- Cas où on a le jour (en chiffres) et le mois
		if tab.test_quantieme and tab.test_mois then
			if tab.afficher_jour then
-- Cas particulier pour la mise en forme de "1er", "2e", etc.
				if not (tab.exposant_jour == '') then
					jour = tab.quantieme..tab.exposant_jour
					jour_affiche = '<abbr class="abbr" title="'..infobulle[jour]..'" >'..tab.quantieme..'<sup>'..tab.exposant_jour..'</sup></abbr>'
				else
					jour = tab.quantieme
					jour_affiche = tab.quantieme
				end
				if tab.lien_jour then
					article = jour..' '..tab.mois
					if listeArticlesJours[article] then
-- Si l'index formé par l'ensemble jour-mois existe dans la table, c'est qu'un article wikipédia existe => lien [[jour mois]
-- Sinon => lien sur le mois seulement (les articles sur les mois existent dans tous les cas)
						date_affichee = date_affichee..'[['..article..'|'..jour_affiche..']]'
					else
						date_affichee = date_affichee..jour_affiche
					end
				else
					date_affichee = date_affichee..jour_affiche
				end
			end
			if tab.afficher_mois then
				if date_affichee == '' then
					tab.mois = string.sub(tab.mois_saisi, 1, 1)..string.sub(tab.mois, 2)
				end
				if tab.lien_mois then
					date_affichee = date_affichee..' [['..tab.mois..']]'
				else
					date_affichee = date_affichee..' '..tab.mois
				end
			end
		else
-- Cas où seul le nom précis d'un des jours complémentaires est présent,
-- si demandé on affiche le lien (les articles sur ces jours existent dans tous les cas)
			if tab.test_jour_complementaire and tab.afficher_jour then
				if tab.lien_jour then
					date_affichee = '[['..tab.quantieme..']]'
				else
					date_affichee = tab.quantieme
				end
			else
-- Cas où seul le mois est présent, si demandé on affiche le lien (les articles sur les mois existent dans tous les cas)
				if tab.test_mois and tab.afficher_mois then
					tab.mois = string.sub(mois_saisi, 1, 1)..string.sub(tab_mois, 2)
					if tab.lien_mois then
						date_affichee = '[['..tab.mois..']]'
					else
						date_affichee = tab.mois
					end
				end
			end
		end
	else
-- Cas où l'année est renseignée

-- Cas des dates sous la forme jour_complémentaire année
-- Traitement du jour
		if tab.test_jour_complementaire and tab.afficher_jour then
			if tab.lien_jour then
-- On vérifie dans la table s'il existe un article dont le lien est de la forme [[jour complémentaire an XX]]
-- Si ce n'est pas le cas, on affiche un lien sur le jour seul
				article = tab.quantieme..' an '..tab.an
				if listeArticlesMois[article] then
					date_affichee = '[['..article..'|'..tab.quantieme..']]'
				else
					date_affichee = '[['..tab.quantieme..']]'
				end
			else
-- Pas de lien demandé
 				date_affichee = date_affichee..tab.quantieme
			end
			if tab.afficher_an then
-- Traitement de l'année
				tab.test, chaine = p.annee_affichee(tab.an, tab.lien_an)
				date_affichee = date_affichee..' '..chaine
			end
		end

-- Cas des dates sous la forme jour mois année
-- Traitement du jour
		if tab.test_quantieme and tab.test_mois	then
			if tab.afficher_jour then
-- Cas particulier pour la mise en forme de "1er", "2e", etc.
				if not (tab.exposant_jour == '') then
					jour = tab.quantieme..tab.exposant_jour
					jour_affiche = '<abbr class="abbr" title="'..infobulle[jour]..'" >'..tab.quantieme..'<sup>'..tab.exposant_jour..'</sup></abbr>'
				else
					jour = tab.quantieme
					jour_affiche = tab.quantieme
				end
				article = jour..' '..tab.mois
-- Si l'index formé par l'ensemble jour-mois existe dans la table, c'est qu'un article wikipédia existe => lien [[jour mois|jour]]
-- Sinon => lien sur le mois seulement (les articles sur les mois existent dans tous les cas)
				if tab.lien_jour and listeArticlesJours[article] then
					date_affichee = '[['..article..'|'..jour_affiche..']]'
				else
					date_affichee = jour_affiche
				end
			end
			if tab.afficher_mois then
				if tab.lien_mois then
					if date_affichee == '' then
						tab.mois = string.sub(tab.mois_saisi, 1, 1)..string.sub(tab.mois, 2)
					end
					article = tab.mois..' an '..tab.an
					if listeArticlesMois[article] then
						date_affichee = date_affichee..' [['..article..'|'..tab.mois..']]'
					else
						date_affichee = date_affichee..' [['..tab.mois..']]'
					end
				else
					date_affichee = date_affichee..' '..tab.mois
				end
			end
					
			if tab.afficher_an then
				if not (date_affichee == '')
				and ((string.upper(string.sub (tab.libelle_an, 1, 1)) == 'A') or (tab.libelle_an == '')) then
					tab.libelle_an = nil
				end
				tab.test, chaine = p.annee_affichee (tab.an, tab.lien_an, tab.libelle_an)
				if not tab.test	then
					return chaine
				else
					date_affichee = date_affichee..' '..chaine
				end
			end
		end
	
-- Cas où il n'y a pas de numéro de jour, date de la forme    mois année
-- On vérifie dans la table s'il existe un article dont le lien est de la forme [[mois an XX]]
-- Si ce n'est pas le cas, on affiche un lien sur le mois seul
		if tab.test_mois and not tab.test_quantieme and tab.afficher_mois then
			if date_affichee == '' then
				tab.mois = string.sub(tab.mois_saisi, 1, 1)..string.sub(tab.mois, 2)
			end
			article = tab.mois..' an '..tab.an
			if tab.lien_mois then
				if listeArticlesMois[article] then
					date_affichee = '[['..article..'|'..tab.mois..']]'
				else
					date_affichee = '[['..tab.mois..']]'
				end
			else
				date_affichee = tab.mois
			end
					
			if tab.afficher_an then
				tab.test, chaine = p.annee_affichee (tab.an, tab.lien_an)
				date_affichee = date_affichee..' '..chaine
			end
		end
-- Cas où on n'affiche que l'année
		if tab.afficher_an and (date_affichee == '') then
			tab.test, date_affichee = p.annee_affichee(tab.an, tab.lien_an, tab.libelle_an)
			if not tab.test then
				date_affichee = p.categorie_erreur (tab.nocat, date_affichee)
				return date_affichee
			end
 		end
	end

-- Si la date présente des espaces, on les rend insécables
	if date_affichee:match( ' ' ) then
		date_affichee = '<span class="nowrap">'..date_affichee..'</span>'
	end

-- Mise en forme de l'éventuelle date correspondante dans le calendrier grégorien

-- Cette possibilité est activée par le passage d'une chaine de caracère contenant "conversion" ou "grégorien"
	if test_conversion or test_conversion_sans_liens then
		if ((tab.test_quantieme and tab.test_mois) or tab.test_jour_complementaire) and tab.test_an	then
			if tab.test_jour_complementaire then
				tab.mois = 'jour complémentaire'
			end
			tab.test, tab.message, jour_Greg, mois_Greg, an_Greg = p.conversion_Gregorien(tab.quantieme, tab.mois, tab.an)
			if tab.test	then
-- Si le paramètre contenant la chaine conversion présente le caractère « : » (deux points),
-- le résultat est présenté sous la forme      date républicaine : date gégorienne
-- Sinon, le le résultat est présenté sous la forme      date républicaine (date gégorienne)
				if deux_points then
					date_affichee = date_affichee..' : '
				else
					date_affichee = date_affichee..' ('
				end
-- § La mention facultative de j, jm, a, etc. permet de selectionner ce qui est conservé à l'affichage de la date grégorienne
-- cela permet de faire appel au module date en utilisant les "-" qui masquent l'affichage des éléments non souhaités
-- § conversion* permet d'afficher la date grégorienne sans liens
				if test_conversion_sans_liens then
					if conv_jour_mois then
						date_affichee = date_affichee..modeleDate({jour_Greg, mois_Greg, an_Greg..'-', nolinks="oui"})
					elseif conv_jour then
						date_affichee = date_affichee..modeleDate({jour_Greg, mois_Greg..'-', an_Greg..'-', nolinks="oui"})
					elseif conv_mois_an then
						date_affichee = date_affichee..modeleDate({nil, mois_Greg, an_Greg, nolinks="oui"})
					elseif conv_an then
						date_affichee = date_affichee..an_Greg
					else
						date_affichee = date_affichee..modeleDate({jour_Greg, mois_Greg, an_Greg, nolinks="oui"})
					end
				else
					if conv_jour_mois then
						date_affichee = date_affichee..modeleDate({jour_Greg, mois_Greg, an_Greg..'-'})
					elseif conv_jour then
						date_affichee = date_affichee..modeleDate({jour_Greg, mois_Greg..'-', an_Greg..'-'})
					elseif conv_mois_an then
						date_affichee = date_affichee..modeleDate({nil, mois_Greg, an_Greg})
					elseif conv_an then
						date_affichee = date_affichee..'[['..an_Greg..']]'
					else
						date_affichee = date_affichee..modeleDate({jour_Greg, mois_Greg, an_Greg})
					end
				end
				if not deux_points then
					date_affichee = date_affichee..')'
				end
			else
				date_affichee = date_affichee..message
			end
		else
			tab.test = false
			date_affichee = '<span class="error">conversion impossible, date incomplète</span>'
		end
	end
	

			
	if not tab.test then
		date_affichee = p.categorie_erreur (date_affichee)
	end
	
	return date_affichee
end

function p.categorie_erreur (nocat, message)
 	local namespaceCategorisation = { [0] = true, [4] = true, [10] = true, [14] = true, [100] = true }
--	local namespaceCategorisation = { [4] = true }
	if namespaceCategorisation[ mw.title.getCurrentTitle().namespace ] and (nocat=='') then
		return message .. '[[Catégorie:Page avec une erreur de paramètre du modèle Date républicaine]]'
	else
		return message
	end
end

-- Fonction permettant la mie en forme typographique et l'établissement des liens possibles sur une date du calendrier républicain
-- en vigueur en France entre 1792 et 1806 ainsi qu'en 1871 pendant la Commune. Il est également possible de faire afficher
-- la date grégorienne correspondante en indiquant "conversion" en paramètre.
function p.date_republicaine (frame)
	local args = Outils.extractArgs(frame)
	local aucun_lien = false
	
	local chaine = p._date_republicaine (aucun_lien, args)

	return chaine
end

-- Fonction permettant la mie en forme typographique sur une date du calendrier républicain
-- en vigueur en France entre 1792 et 1806 ainsi qu'en 1871 pendant la Commune. Il est également possible de faire afficher
-- la date grégorienne correspondante en indiquant "conversion" en paramètre.
function p.date_republicaine_sans_liens (frame)
	local args = Outils.extractArgs(frame)
	local aucun_lien = true
	
	local chaine = p._date_republicaine (aucun_lien, args)

	return chaine
end

return p