Module:Dâta
Aparence
La documentation pour ce module peut être créée à Module:Dâta/doc
-- luacheck: globals mw, no max line length
local fun = {}
local Outils = require 'Module:Outils'
-- chargement de la base de données 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 où 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 fonctions qui l'utilisent.
local trim = Outils.trim
-- Fonction destinée à mettre la première lettre du mois en majuscule :
-- utilisation de string car aucun mois ne commence 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.', 'feb', 'february' } },
{ num = 3, nJorn = 31, abrev = 'mârs', nom = 'de mârs', alias = { 'mârs', 'mars', 'mâr.', 'mâr', 'mar.', 'mar', 'march' } },
{ num = 4, nJorn = 30, abrev = 'avr.', nom = 'd’avril', alias = { 'avril', 'avr.', 'avr', 'apr.', '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.', 'jul', 'july' } },
{ num = 8, nJorn = 31, abrev = 'oût', nom = 'd’oût', alias = { 'oût', 'out', 'aug.', '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 = 'oût', nom = 'd’oût', alias = { 'oût', 'out' } },
}
-- ajoute les noms, abréviations et alias en tant que clés de listeMois
for i = 1, 12 do
local mes = listaMes[ i ]
listaMes[tostring( i )] = mes
if i < 10 then
listaMes['0' .. i] = mes
end
listaMes[mes.nom] = mes
listaMes[mes.abrev] = mes
for j = 1, #mes.alias do
listaMes[mes.alias[j]] = mes
end
end
for i = 1, #listaMes.out.alias do
listaMes[listaMes.out.alias[i]] = listaMes.out
end
local lista_sesons = {
{ 'forél', 'spring', },
{ 'chôd-temps', 'summer', },
{ 'ôton', 'autumn', },
{ 'hivèrn', 'winter', },
}
-- à partir d'un nom de saison (en français ou en anglais),
-- retourne son nom canonique (exemple : "été")
-- si non reconnu, retourne nil
function fun.determenacionSeson( seson )
local s = trim( seson )
if s then
s = s:gsub( 'C', 'c' ):lower()
for i = 1, 4 do
for j = 1, #lista_sesons[i] do
if s == lista_sesons[i][j] then
return lista_sesons[i][1]
end
end
end
end
end
---
-- à partir d'un nom de mois (en français ou en anglais), de son numéro ou d'une abréviation,
-- retourne son nom canonique (exemple : "juin") et son numéro (exemple : 6)
-- si non reconnu, retourne nil, nil
function fun.determenacionMes( mes )
local result
local num = tonumber( mes )
if num then
result = listaMes[num]
else
local str = trim( mes )
if str then
result = listaMes[str]
if not result then
result = listaMes[str:gsub( 'C', 'c' ):gsub( 'Û', 'û' ):lower()]
end
end
end
if result then
return result.nom, result.num
else
return nil, nil
end
end
-- fonction interne à modeleDate, pour déterminer si on peut se passer de faire un ifexist
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 remplacé par celui de la base de données, ce qui permet des alias.
local lim = an
if dataQualificatif.qualificatif ~= '' then
lim = lim .. ' ' .. dataQualificatif.qualificatif
end
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 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'année 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 = 1, #nomJorn do
jorn = jorn:gsub( nomJorn[i], '' )
end
for i = 1, #premier do
jorn = jorn:gsub( premier[i], '1' )
end
jorn = trim( jorn )
end
return jorn
end
---
-- Sépare une chaine date en une 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 .. ' envalido (' .. valor .. ')</span>'
end
local dataDevantCleanup = date
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 mmm2 = '([^%s%p%d]+[.]?[-/][^%s%p%d]+[.]?)' -- mois-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
date = fun.neteyajoJorn( date )
if date == nil then
return fota( 'Dâta', dataDevantCleanup )
end
if date:find( '[[', nil, true ) then
date = date
-- suppression catégories (doit être exécuté avant le code de suppression des liens)
:gsub( '%[%[[Cc]atègorie:.-%]%]', '' )
:gsub( '%[%[[Cc]ategory:.-%]%]', '' )
-- suppression liens
:gsub( '%[%[([^%[%]|]*)|?([^%[%]]*)%]%]', function ( l, t ) return trim( t ) or l end )
end
date = date
-- suppression balises
:gsub( '%b<>', '' )
-- suppression des espaces insécables
-- nbsp
:gsub( '\194\160', ' ' )
:gsub( ' ', ' ' )
:gsub( ' ', ' ' )
-- narrow nbsp
:gsub( '\226\128\175', ' ' )
:gsub( ' ', ' ' )
-- thin space
:gsub( '\226\128\137', ' ' )
:gsub( ' ', ' ' )
:gsub( ' ', ' ' )
-- simple space
:gsub( ' ', ' ' )
-- plusieurs espaces (doit être exécuté après les autres remplacements)
:gsub( ' +', ' ' )
-- réduction av. J-C pour simplifier un peu les regex
:gsub( '(%d+) ?[Dd][Ee][Vv]%.? ?[Jj][ .-]*[Cc]%.?', '-%1' )
-- suppression de l'heure dans les dates 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', dataDevantCleanup )
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( '^'..mmm2..s..aj..muens..'$' ) then
-- mmm-mmm aaaa
mes, separator, an, cachierAn = date:match( '^'..mmm2..sep..aj..muens..'$' )
if separator:match( '^.+%-$' ) then
an = '-' .. an
end
elseif date:match( '^'..j..s..mmm..muens..'$' ) then
-- jj mmm
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', dataDevantCleanup )
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 que les paramètres correspondent à une date valide.
-- la date peut être dans les paramètres 1 à 3, ou dans des paramètres jour, mois et annee.
-- La fonction retourne true suivi d'une table avec la date en paramètres nommés (sans accent sur année)
-- ou false suivi d'un message d'erreur.
function fun.validacionJornMesAn( frame )
local args = Outils.extractArgs( frame )
local jorn, mes, numMes, an
local bjorn = args['jorn'] or args[1] or ''
local bmes = tostring( args['mês'] or args[2] or '' )
local ban = args['an'] or args[3] or ''
local function fota( temps, valor )
return false, '<span class="error">' .. temps .. ' envalido (' .. 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 = ban:match( '^(%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.determenacionMes( bmes )
if mes == nil then
mes = fun.determenacionSeson( bmes )
if mes == nil then
local mes1, sep, mes2 = bmes:match( '^([^%s%p%d]+[.]?)([-/])([^%s%p%d]+[.]?)$' )
if mes1 then
mes1 = fun.determenacionMes( mes1 )
mes2 = fun.determenacionMes( mes2 )
if mes1 == nil or mes2 == nil then
return fota( 'Mês', bmes )
end
mes = mes1 .. sep .. mes2
else
return fota( 'Mês', bmes )
end
end
end
-- on traite le jour si présent
if Outils.notEmpty( bjorn ) then
if not numMes then
fota( 'Dâta', 'jorn avouéc sêson ou ben un mouél de mês' )
end
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
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 dates négatives
-- âge : ajoute la durée depuis cette date
-- agePrefix : préfixe pour l'age, 'à ' par défaut pour les décès
-- liens : active les liens par défaut
-- nolinks : ne met pas de lien sur la date (a précédence sur le paramètre "liens")
-- afficherErreurs : en cas d'erreur, si défini à "non" ne retourne pas un message d'erreur, mais le 1er argument inchangé
-- categoriserErreurs : en cas d'erreur, si défini à "non" ne catégorise pas ; peut aussi être défini avec une catégorie à utiliser à la place de celle par défaut
-- naissance : ajoute la class "bday"
-- mort : ajoute la class "dday"
function fun.modeloData( frame )
local Yesno = require 'Module:Yesno'
local args
if frame. args and frame.args.nogetparent then args = frame.args else args = Outils.extractArgs( frame ) end
-- l'import des paramètres passés au modèle appelant et non au #invoke est désactivable par nogetparent
for i,j in ipairs(args) do args[i] = tostring(j) end
local resultat
local dataNessenceMort
local cherchedovesdates = args.mort or args['èvènament'] or args.evenament
-- analyse des paramètres non nommés (ou paramètres de la date jour, mois, annee)
local eprova, params
local arg1, arg2, arg3, arg4 = fun.neteyajoJorn( args[1] ), trim( args[2] ), trim( args[3] ), trim( args[4] )
if cherchedovesdates then args2 = fun.neteyajoJorn( args2 ) end
local slashesinarg1 = arg1 and arg1:match( '[^ ./-][ ./-]+[^ ./-]' )
local slashesinarg2 = cherchedovesdates and arg2 and arg2:match( '[^ ./-][ ./-]+[^ ./-]' )
if arg1 and not arg3 and ((slashesinarg1 and not cherchedovesdates) or arg2 == nil or dataLims[arg2] or mw.ustring.match( arg2, '%a %a' ) ) then
-- une date dans le premier paramètre
eprova, params = fun.separacionJornMesAn( arg1 )
if eprova then
dataNessenceMort = trim( arg2 )
params.qualificatif = trim( arg2 )
end
elseif type( arg1 ) == 'string' and type( arg2 ) == 'string' and arg3 ~= nil and arg4 == nil and ( arg1:match( '[^ ./-][ ./-]+[^ ./-]' ) or dataLims[arg3] or mw.ustring.match( arg3, '%a %a' ) ) then
-- la date est dans le premier paramètre
eprova, params = fun.separacionJornMesAn( arg1 )
if eprova then
if dataLims[trim( arg2 )] then
params.qualificatif = trim( arg2 )
end
end
elseif cherchedovesdates and (not arg4) and ( slashesinarg1 or slashesinarg2 or dataLims[arg3] or (arg3 and mw.ustring.match( arg3, '%a %a' ) ) ) then
-- deux dates dans les deux premiers paramètres
eprova, params = fun.separacionJornMesAn( arg1 )
if eprova then
dataNessenceMort = trim( arg2 )
if dataLims[trim( arg3 )] then
params.qualificatif = trim( arg3 )
end
end
else
local cleanArgs = {jorn = args.jorn, mes = args.mes, an = args.an or args['an']}
if arg1 and listaMes[arg1] and not tonumber(arg1) then --le premier argument est un mois donc le deuxième est présumé année
cleanArgs.mes = (cleanArgs.mes or arg1)
cleanArgs.an = cleanArgs.an or arg2
cleanArgs.qualificatif = arg3
else
cleanArgs.jorn = cleanArgs.jorn or arg1
cleanArgs.mes = cleanArgs.mes or arg2
cleanArgs.an = cleanArgs.an or arg3
cleanArgs.qualificatif = arg4
end
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
cleanArgs.mees, cleanArgs.cachierMes = cachierParam( cleanArgs.mes )
cleanArgs.an, cleanArgs.cachierAn = cachierParam( cleanArgs.an )
-- Si les paramètres ont été envoyés directement, ils ont précédence
if args.cachierMes then cleanArgs.cachierMes = args.cachierMes end
if args.cachierAn then cleanArgs.cachierAn = args.cachierAn end
eprova, params = fun.validacionJornMesAn( cleanArgs )
if eprova and dataLims[trim( cleanArgs.qualificatif )] then
params.qualificatif = trim( cleanArgs.qualificatif )
end
end
-- analyse des paramètres nommés
if eprova then
params.ajoPrefix = args.ajoPrefix
if args.qualificatif and dataLims[args.qualificatif] then
params.qualificatif = args.qualificatif
end
-- julien peut avoir trois valeurs : inactif, format standard (true), format court
params.jelien = Yesno( args.jelien, 'côrt', false )
params.devJC = Yesno( args.devJC )
if args['rèpubliquen'] and args['rèpubliquen'] ~= '' then
if args['rèpubliquen'] == 'lims' then
params.republiquen = 'lims'
else
params.republiquen = Yesno( args['rèpubliquen'], false )
end
else
params.republiquen = false
end
if args.dataNessenceMort and args.dataNessenceMort ~= '' then
dataNessenceMort = args.dataNessenceMort
elseif args['dâtaNèssenceÈvènament'] and args['dâtaNèssenceÈvènament'] ~= '' then
dataNessenceMort = args['dâtaNèssenceÈvènament']
end
if dataNessenceMort then
local eprovaNessenceMort, paramsNessenceMort = fun.separacionJornMesAn( dataNessenceMort )
if eprovaNessenceMort then
params.anNessenceMort, params.mesNessenceMort, params.numMesNessenceMort, params.jornNessenceMort = paramsNessenceMort.an, paramsNessenceMort.mes, paramsNessenceMort.numMes, paramsNessenceMort.jorn
end
end
local listaParam = {
ajo = 'âjo',
['âjo'] = 'âjo',
nessence = 'nèssence',
['nèssence'] = 'nèssence',
mort = 'môrt',
['môrt'] = 'môrt',
apJC = 'apJC',
nolinks = 'nolinks',
compact = 'compacto',
compacto = 'compacto',
}
for n, v in pairs( listaParam ) do
params[v] = params[v] or Yesno( args[n], true, false ) or nil
end
if not params.nolinks then
local lims = Yesno( args.lims )
if lims == nil then
-- liens actifs par défaut si qualificatif
lims = params.qualificatif and params.qualificatif ~= "" and true or false
end
params.nolinks = not lims
end
-- sortie pour les tests unitaire, ou pour débugger
if args.debug then
return params
end
resultat = fun._modeloData( params )
else
local yn_farevereFotes = Yesno( args.farevereFotes )
if yn_farevereFotes == nil or yn_farevereFotes == true then
resultat = params
else
resultat = args[1]
end
local currentTitle = mw.title.getCurrentTitle()
if currentTitle:inNamespaces( 0, 4, 10, 14, 100 )
and not Outils.notEmpty( args.nocat )
and not currentTitle.prefixedText:match( '^Modèlo:.+/Èprôva$' ) then
local categoria
local yn_categorisarFotes = Yesno( args.categorisarFotes, 'custom', true )
if yn_categorisarFotes == nil or yn_categorisarFotes == true then
categoria = '[[Catègorie:Pâge qu’emplèye lo modèlo dâta avouéc na sintaxa fôssa]]'
elseif yn_categorisarFotes == false then
categoria = ''
else
local nomCategoria = args.categorisarFotes
:gsub( '^%[%[', '' )
:gsub( '%]%]$', '' )
:gsub( '^:?[Cc]atègorie:', '' )
:gsub( '^:?[Cc]atègory:', '' )
categoria = '[[Catègorie:' .. nomCategoria .. ']]'
end
resultat = resultat .. categoria
end
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'âge, naissance et mort
local ajoPrefix = args.ajoPrefix
local ajo = args['âjo'] and fun.ajo( an, numMes, jorn )
local nessence = args['nèssence'] or args.nessence
local mort = args['môrt'] or args.mort
local evenament = args['èvènament'] or args.evenament
if mort and args.anNessenceMort then
ajo = fun.ajo( args.anNessenceMort, args.numMesNessenceMort, args.jornNessenceMort, an, numMes, jorn )
ajoPrefix = ajoPrefix or 'a ' -- faut-il mettre \194\160 ?
elseif evenament and args.anNessenceMort then
if nessence then
ajo = fun.ajo( an, numMes, jorn, args.anNessenceMort, args.numMesNessenceMort, args.jornNessenceMort )
else
ajo = fun.ajo(args.anNessenceMort, args.numMesNessenceMort, args.jornNessenceMort, an, numMes, jorn )
end
end
ajoPrefix = ajoPrefix or ''
-- 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 jelienData, jelienSup, jelienSep -- servira éventuellement à afficher la date selon le calendrier julien
local gregAprMes, gregAprAn, gregFin -- message de calendrier grégorien lorsque la date est selon le calendrier julien
local dataRepubliquena
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
if args.jelien == 'côrt' then
jelienData = jjorn .. ' ' .. jmes .. ' '
jelienSup = '<sup>[[calendriér jelien|jel.]]</sup>'
if jan == an then
gregAprMes = '<sup>[[calendriér grègorien|grèg.]]</sup>'
else
jelienData = jelienData .. jan .. ' '
gregAprAn = '<sup>[[calendriér grègorien|grèg.]]</sup>'
end
jelienSep = ' / '
else
jelienData = jjorn .. ' ' .. jmes .. ' ' .. jan
jelienSep = ' ('
gregFin = ' [[Passâjo du calendriér jelien u calendriér grègorien|dens lo calendriér grègorien]])'
end
elseif args.republiquen then
local DataRep = require 'Module:Dâta rèpubliquèna'
local RepSenLims
if args.republiquen == 'lims' then
RepSenLims = false
else
RepSenLims = true
end
dataRepubliquena = DataRep._data_republiquena(
RepSenLims,
{ fun.formatRepCal( fun.do_toRepCal{gan, gmes, gjorn} ) }
)
end
else
if an and an < 0 then
gan = gan + 1
end
args.jelien = false
args.republiquen = false
end
-- on génère le résultat
-- Déclarations des variables
local wikiLista = {} -- reçoit le texte affiché pour chaque paramètre
local iso = {} -- reçoit 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 not numMes then
-- mois est autre chose qu'un simple mois : saison, mois-mois... auquel cas, pas d'abréviation (provoquait erreur Lua)
-- (les abréviations pour le cas "mois[-/]mois" seraient théoriquement possibles, mais ça reste à implémenter)
else
if args.nolinks then
textoMes = '<abbr class="abbr" title="' .. mes .. '">' .. listaMes[mes].abrev .. '</abbr>'
else
textoMes = listaMes[mes].abrev
end
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 qualificatif n'est pas dans la base de données, on crée une table minimum,
-- qui imposera un test sur l'année, 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
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 textoJorn, lim
if jorn == 1 then
textoJorn = '1<sup>ér</sup>'
lim = '1ér ' .. mes
else
textoJorn = jorn
lim = jorn .. ' ' .. mes
end
if qualifJorn ~= '' then
lim = lim .. ' ' .. qualifJorn
end
-- s'il n'y a pas de lien sur le mois, il sera affiché avec le jour.
table.insert( wikiLista, wikiLim( lim, textoJorn ) )
table.insert( wikiLista, wikiLim( lim, textoJorn .. ' '.. 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
if not numMes then
-- mois est autre chose qu'un simple mois : saison, mois-mois... auquel cas, pas de lien
else
lim = existData( dataQualificatif, an, mes ) or existData( dataCat, an, mes )
if lim == nil and qualificatif and qualifJorn == '' then
-- 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
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, gregAprMes )
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
if an < 0 then
local anDevJc = 0 - an
if args.devJC == false then
textoAn = anDevJc
else
textoAn = anDevJc .. ' <abbr class="abbr" title="'
.. 'devant Jèsus-Crist">dev. J.-C.</abbr>'
end
elseif args.apJC then
textoAn = textoAn .. ' <abbr class="abbr" title="'
.. 'aprés Jèsus-Crist">apr. J.-C.</abbr>'
end
if args.nolinks then -- seulement si on doit l'afficher
table.insert( wikiLista, textoAn )
else
local lim = existData( dataQualificatif, an ) or existData( dataCat, an )
if not lim then
if an < 0 then
local anDevJc = 0 - an
lim = anDevJc .. ' dev. J.-C.'
else
lim = an
end
end
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
end
if an then
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, gregAprAn )
-- l'age
if type( ajo ) == 'number' and ajo >= 0 and ( not nessence or ajo < 120 ) then
if ajo == 0 then
ajo = '(' .. ajoPrefix .. 'muens d’un\194\160an)'
elseif ajo == 1 then
ajo = '(' .. ajoPrefix .. '1\194\160an)'
else
ajo = '('.. ajoPrefix .. ajo .. '\194\160ans)'
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( '' )
if jelienData then
wikiHtml:tag( 'span')
:addClass( 'nowrap' )
:attr( 'data-sort-value', isoTexto )
:wikitext( jelienData )
:node( jelienSup )
:done()
:wikitext( jelienSep )
end
local dataHtml = wikiHtml:tag( 'time' )
:wikitext( wikiTexto )
if wikiTexto:match( ' ' ) then
dataHtml:addClass( 'nowrap' )
end
if isoTexto ~= wikiTexto then
dataHtml:attr( 'datetime', isoTexto )
:attr( 'data-sort-value', 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( gregFin )
if dataRepubliquena then
wikiHtml:wikitext( ' (', dataRepubliquena, ')' )
end
if ajo then
wikiHtml:wikitext( ' ' )
:tag( 'span' )
:addClass( 'noprint')
:wikitext( ajo )
:done()
end
return tostring( wikiHtml )
end
-- isoJourMoisAnnee transforme une date iso en un tableau équivalent à celui retourné par separationJourMoisAnnee
local function isoJornMesAn( dataiso )
if dataiso and dataiso:sub( 1, 2 ) == 'U-' then
dataiso = dataiso:sub( 2 )
end
local an, mes, jorn = dataiso:match( '^(%-?%d%d%d%d+)%-(%d+)%-(%d+)$' )
if not an then
an, mes = dataiso:match( '^(%-?%d%d%d%d+)%-(%d+)$' )
end
if not an then
an = dataiso:match( '^(%-?%d%d%d%d+)$' )
end
if an and tonumber( an ) <= 0 then
-- la date iso utilise une année 0
an = tonumber( an ) - 1
end
if not an then
mes, jorn = dataiso:match( '^(%d+)%-(%d+)$' )
end
return fun.validacionJornMesAn{ jorn, mes, an }
end
-- analyseDate sépare la date du contenu qui précède et suit, supprime les liens, et retourne si possible une table avec jour mois année
local function analisaData( d )
if trim( d ) then
local datesMultiples = d:match( ' ou ben ' ) or d:match( '^[Ee]ntre-mié ' ) or d:match( '<time.->.-<time.->' )
if datesMultiples then
return d
end
local aprox = d:match( '^[Dd]e vers ' ) or d:match( '^[Aa]prés ' ) or d:match( '^[Dd]evant ' )
-- booléen qui indique que la date est approximative, empêchant l'affichage de l'âge ou de la durée
aprox = aprox and true or false
local analisa = d
-- s'il s'agit d'une date formattée avec {{date}}, on utilisera la valeur du datetime pour reconstruire la date
local dataiso = d:match( 'datetime="([U%d-]+)"' ) or d:match( '<time>(.-)</time>' )
local comencement, strData, fin
if dataiso then
-- supprime le formatage créé par {{date}}
comencement, strData, fin = analisa:match( '(.-)<time.->(.-)</time>(.*)' )
end
if not strData then
-- sépare une date av. J.-C. du contenu qui suit
strData, fin = analisa:match( '(.-%d av%. J%.%-C%.]*%-?)(.*)' )
end
if not strData then
-- sépare la date (avec ses liens) d'une référence ou contenu commençant par un espace
strData, fin = analisa:match( '(.-%d%d%d%]*%-?)([\127 ].+)' )
end
if not strData then
-- sépare la date du contenu commençant par <br>
strData, fin = analisa:match( '(.-%d%d%d%]*%-?)(<br ?/?>.+)' )
end
analisa = strData or analisa
-- supprime les liens
analisa = analisa:gsub(
'%[%[([^%[%]|]*)|?([^%[%]]*)%]%]',
function ( l, t )
return trim( t ) or l
end
)
local t, r
if dataiso then
-- Si la date était formatée avec {{date}}, on la reconstruit à partir de la valeur de datetime
t, r = isoJornMesAn( dataiso )
end
if t then
local tTexto, rTexto = fun.separacionJornMesAn( analisa )
if r.an and r.jorn then
local amj = r.an * 10000 + r.numMes * 100 + r.jorn
-- Les dates avant le 14 octobre 1582 sont dans le calendrier julien mais utilisent un datetime grégorien
local gregToJul = amj < 15821014
if not gregToJul and amj < 15821024 then
-- Entre le 14 et le 23 octobre, on ne peut pas différencier entre julien et grégorien sans comparer avec le texte
gregToJul = tTexto and rTexto.jorn ~= r.jorn
end
if gregToJul then
local jan, jmes, jjorn = fun.gregorianToJulian( r.an, r.numMes, r.jorn )
r = {
an = jan,
numMes = jmes,
mes = listaMes[jmes].nom,
jorn = jjorn
}
end
end
if tTexto then
-- On analyse le texte de la date pour repérer les dates partiellement masquées
-- Si seul le jour est affiché, separationJourMoisAnnee l'interprète comme une année
if not rTexto.jorn and not rTexto.mes and rTexto.an == r.jorn then
r.cachierMes = true
r.cachierAn = true
elseif rTexto.jorn == r.jorn and rTexto.mes == r.mes and not rTexto.an then
r.cachierAn = true
end
end
else
t, r = fun.separacionJornMesAn( analisa )
end
if t then
return r, fin, comencement, aprox
else
return d, fin, comencement, aprox
end
end
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és pour gérer les cas où
-- le paramètre contient déjà un modèle date.
-- Paramètres :
-- 1 : type de date à afficher (naissance / n, mort / m, ou date / d)
-- 2 : Date ou date de naissance
-- 3 : 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
-- 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( dataString )
if dataString then
local datetime = dataString:match( 'datetime="([U%d%-]+)"' )
if datetime and datetime:match('%-%d%d%-%d%d') and trim( args['prèfixo'] ) then
return args['prèfixo'] .. ' ' .. dataString
end
if trim( args['prèfixo sen jorn'] ) then
return args['prèfixo sen jorn'] .. ' ' .. dataString
end
end
return dataString
end
local nessence = args[1]:match( '^n' ) == 'n'
local mort = args[1]:match( '^m' ) or args[1]:match( 'môrt' )
local evenament = args[1]:match( '^è' )
local afichajoData, qualificatif = args[2], args[4]
local afichajoDataTab, resultatData, complementData, prefixoData, aproxData
local dataNessence, dataMort, aproxNessence, aproxMort
if mort or evenament then
afichajoData = args[3]
end
if not trim( afichajoData ) then
return
end
if afichajoData:match( ']]</time>' ) or afichajoData: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 or evenament ) and ( afichajoData:match( 'wikidata%-linkback' )) then
local _
dataNessence, _, _, aproxNessence = analisaData( args[2] )
dataMort, _, _, aproxMort = analisaData( args[3] )
resultatData = afichajoData
else
return prefix( afichajoData )
end
else
afichajoDataTab, complementData, prefixoData, aproxData = analisaData( afichajoData )
if type( afichajoDataTab ) ~= 'table' then
return afichajoDataTab
else
if nessence then
local _
dataNessence, aproxNessence = afichajoDataTab, aproxData
dataMort, _, _, aproxMort = analisaData( args[3] )
elseif mort then
local _
dataNessence, _, _, aproxNessence = analisaData( args[2] )
dataMort, aproxMort = afichajoDataTab, aproxData
else
qualificatif = args[3]
end
afichajoDataTab.nessence = not aproxNessence and nessence
afichajoDataTab.mort = not aproxMort and mort
afichajoDataTab.evenament = evenament
afichajoDataTab.qualificatif = args.qualificatif or qualificatif
afichajoDataTab.lims = true -- Dans les infobox, liens activés par défaut
afichajoDataTab.nolinks = args.nolinks
afichajoDataTab.nocat = args.nocat
afichajoDataTab.jelien = args.jelien
end
end
resultatData = resultatData or fun._modeloData( afichajoDataTab )
local ajo, prefixAjo, suffixAjo, carculAjo = '', ' <span class="noprint">(', ')</span>', nil
if nessence and
dataNessence and
not aproxNessence and
not dataMort and
type( dataNessence ) == 'table'
then
carculAjo = fun.ajo( dataNessence.an, dataNessence.numMes, dataNessence.jorn )
if carculAjo and carculAjo > 120 then
carculAjo = nil
end
elseif ( mort or evenament ) and
dataNessence and
dataMort and
not aproxNessence and
not aproxMort and
type( dataNessence ) == 'table'
and type( dataMort ) == 'table'
then
carculAjo = fun.ajo(
dataNessence.an,
dataNessence.numMes,
dataNessence.jorn,
dataMort.an,
dataMort.numMes,
dataMort.jorn
)
prefixAjo = ' (tant qu’a '
suffixAjo = ')'
end
if tonumber( carculAjo ) then
if carculAjo > 1 then
ajo = prefixAjo .. carculAjo .. '\194\160ans' .. suffixAjo
elseif carculAjo == 1 then
ajo = prefixAjo .. '‘n\194\160an' .. suffixAjo
elseif carculAjo == 0 then
ajo = prefixAjo .. 'muens d’un\194\160an' .. suffixAjo
end
if complementData and complementData:match( 'ans?%)' ) then
complementData = ''
end
end
return ( prefixoData or '' ) .. prefix( resultatData ) .. ( complementData or '' ) .. ajo
end
function fun.tempsEnfocajon( frame )
local args = frame.args
if type( args ) ~= 'table' or not args[1] then
return
end
-- vérifie si une chaîne semble contenir une durée
local function contintTemps( chena )
return chena and (
mw.ustring.match( chena, '%f[%w]ans?%f[^%w]' ) or
mw.ustring.match( chena, '%f[%w]mês%f[^%w]' ) or
mw.ustring.match( chena, '%f[%w]jorns?%f[^%w]' )
)
end
local jorn1, mes1, an1, jorn2, mes2, an2 = '', '', '', '', '', ''
local t1, fin1, _, aprox1 = analisaData( args[1] )
if aprox1 or type( t1 ) ~= 'table' then
return
end
jorn1 = t1.jorn or ''
mes1 = t1.numMes or ''
an1 = t1.an or ''
if args[2] and args[2] ~= "" then
local t2, fin2, _, aprox2 = analisaData( args[2] )
if aprox2 or type( t2 ) ~= 'table' then
return
end
if contintTemps( fin2 ) then
-- La durée semble déjà renseignée manuellement
return
end
jorn2 = t2.jorn or ''
mes2 = t2.numMes or ''
an2 = t2.an or ''
if an1 == '' or an2 == '' then
-- Mieux vaut ne pas extrapoler l'année
return
end
if ( jorn1 ~= '' and jorn2 == '' ) or
( mes1 ~= '' and mes2 == '' ) then
-- Si la deuxième date est moins précise que la première, mieux vaut ne rien afficher
return
end
elseif an1 == '' or contintTemps( fin1 ) then
-- L'année n'est pas spécifiée ou la durée semble déjà renseignée
return
end
local temps = (require 'Module:Temps').temps({ jorn1, mes1, an1, jorn2, mes2, an2, noerror = true })
if temps then
return '<br /><small>(' .. temps .. ')</small>'
end
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 lettres 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.determenacionMes( 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","Fruitidor"}
local extras = {"de la vèrtu","du genie","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]) .. "\194\160" .. 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'âge en fonction de la ou les dates fournies. La valeur retournée est de type 'number'
-- Paramètres :
-- 1, 2, 3 : année, mois jour de naissance (supposé dans le calendrier grégorien)
-- 4, 5, 6 : année, mois, jour du calcul (facultatif, par défaut la date UTC courante).
function fun.ajo( ann, 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
ann = tonumber( ann )
mn = tonumber( mn )
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 - ann
-- si l'intervalle traverse l'année zéro, il faut soustraire une année
-- parce que cette année n'existe pas dans les calendriers chrétiens
if ann < 0 and ac > 0 then
ajo = ajo - 1
end
if mc == mn then
if jc == nil or jn == nil then
return
end
return ajo - ( jc < jn and 1 or 0 )
else
return ajo - ( mc < mn and 1 or 0 )
end
end
function fun.modeloAjo( frame )
local args = Outils.extractArgs( frame )
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 carcular l’âjo prècis</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'algorithme de la page https://en.wikipedia.org/wiki/Julian_day#Julian_or_Gregorian_calendar_from_Julian_day_number
function fun.julianDayToJulian( julianDay )
local y = 4716
local v = 3
local j = 1401
local u = 5
local m = 2
local s = 153
local n = 12
local w = 2
local r = 4
local B = 274277
local p = 1461
local C = -38
local f = julianDay + j
local e = r * f + v
local g = math.modf( math.fmod( e, p ) / r )
local h = u * g + w
local D = math.modf( math.fmod( h, s ) / u ) + 1
local M = math.fmod( math.modf( h / s ) + m, n ) + 1
local Y = math.modf( e / p ) - y + math.modf( ( n + m - M ) / n )
return Y, M, D
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
--[[
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 correspondants
--]]
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():formatDate("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