« Module:Date » : différence entre les versions

Contenu supprimé Contenu ajouté
retouche de la modification précédente : classification par valeur de décalage
modeleDate : séparation des fonctions d'analyse du décalage, d'analyse des paramètres jour, mois, année et de l'affichage de la date. Amélioration de separationJourMoisAnnee.
Ligne 21 :
end
 
local modelePremier = '<abbr class="abbr" title="premier">1<sup>er</sup></abbr>'
 
-- liste des mois, écriture exacte et simplifiée, en minuscule
Ligne 192 ⟶ 193 :
 
---
-- sépareSépare une chaine date en un tabeltable contenant les champs jour, mois et annee.
-- la date doit contenir le mois.
function fun.separationJourMoisAnnee( date, decalage, args )
function fun.separationJourMoisAnnee( date )
date = trim( date )
if date then
Ligne 199 ⟶ 201 :
return false, Outils.erreur( periode .. ' invalide (' .. valeur .. ')' )
end
local jour, mois, annee, masquerMois, masquerAnnee
decalage = decalage or 0
-- variable pour construire les regex
args = args or {}
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 moins = '(%-?)' -- signe moins pour signifier qu'il ne faut pas afficher cette donnée
local regexb = {
jmmm = '^'..j..s..mmm..moins..'$',
mmmjva = '^'..mmm..s..j..', ?'..aj..'$',
}
date = fun.nettoyageJour( date )
-- réduction av. J-C pour simplifier un peu les regex :
local annee = string.match( date, '^%d%d%d%d?$' )
date = date:gsub( '(%d+) ?[Aa][Vv]%.? ?[Jj][ .-]*[Cc]%.?', '-%1' )
if annee then
-- gestion de 1er
return fun.validationJourMoisAnnee{ '', '', annee, args[2 + decalage], decalage = decalage }
date = date:gsub( modelePremier, '1' ):gsub( '%f[%d]1er', '1' )
end
-- supression de l'heure dans les date ISO
-- test date au format jj-mm-aaaa ou jj.mm.aaaa
local j, m, adate = string.matchdate:gsub( date, '^+?([0%d-3]?*%d)[%d%-.]([^ /.-]+%d%d)T%d%d[-.]*(%d*[ AVJCavjc:,.+-]*)Z?$' , '%1')
 
if not m then
-- test année seule
-- test date aux formats jj/mm/aaaa ou dd mmm aaaa
if date:match( '^'..aj..'$' ) then
j, m, a = string.match( date, '^([0-3]?%d)[ /]+([^ /-]+)[ /]*(-?%d*[ AVJCavjc.-]*)$' )
annee = date:match( '^'..aj..'$' )
end
elseif date:match( '^'..aj..s..aj..moins..'$' ) then
if not m then
-- test date aux formats aaaa-jj/mm-jj, aaaa/mm/jjaaaa etou aaaa/mm mmm jj
local a, mb, jsb = string.date:match( date, '^(-?%d%d*)[ /-]+([^ /-]+)[ /-]*([0-3]?%d?)'..aj..s..aj..moins..'$' )
a, b = tonumber( a ), tonumber( b )
end
if a > 12 and ( b < 1 or b > 31 ) or
if not m then
b > 12 and ( a < 1 or a > 31 ) then
-- test date aux formats mm/aaaa ou mmm aaaa
return erreur( 'Date', date )
m, a = string.match( date, '^([^ /-]+)-?[ /]*(-?%d*[ AVJCavjc.]*)$' )
elseif b < 1 or b > 31 then
end
mois, annee, masquerAnnee = a, b, sb
if m then
ifelseif decalagea < 01 or a > 31 then
decalageannee, =mois decalage += a, 2b
elseif b > 12 then
end
return erreur( 'Mois', b )
if tonumber( j ) and tonumber( j ) > 31 and tonumber( a ) and tonumber( a ) < 31 then
-- la date est au format aaaa/mm/jj
return fun.validationJourMoisAnnee{ a, m, j, args[2 + decalage], decalage = decalage }
else
jour, mois, masquerMois = a, b, sb
return fun.validationJourMoisAnnee{ j, m, a, args[2 + decalage], decalage = decalage }
end
elseif date:match( '^'..aj..sep..m..moins..'%2'..aj..moins..'$' ) then
-- jj/mm/aaaa ou aaaa/mm/jj
jour, sep, mois, masquerMois, annee, masquerAnnee = date:match( '^'..aj..sep..m..moins..'%2'..aj..moins..'$' )
if sep == '-' and masquerMois == '-' and masquerAnnee == '' and tonumber( annee ) > 0 then
-- date au format jj-mm--aaaa type 17-06--44 pour 17 juin 44 av. JC
masquerMois = nil
annee = 0 - annee
end
elseif date:match( '^'..j..sep..mmm..moins..'%2'..aj..moins..'$' ) then
-- jj mmm aaaa
jour, sep, mois, masquerMois, annee, masquerAnnee = date:match( '^'..j..sep..mmm..moins..'%2'..aj..moins..'$' )
elseif date:match( '^'..mmm..s..aj..moins..'$' ) then
-- mmm aaaa
mois, annee, masquerAnnee = date:match( '^'..mmm..s..aj..moins..'$' )
elseif date:match( '^'..j..s..mmm..moins..'$' ) then
-- jj mmmm
jour, mois, masquerMois = date:match( '^'..j..s..mmm..moins..'$' )
elseif date:match( '^'..mmm..s..j..', ?'..aj..'$') then
-- mmm jj, aaaa (format anglo-saxon)
mois, jour, annee = date:match( '^'..mmm..s..j..', ?'..aj..'$')
elseif date:match( '^'..mmm..'$' ) then
mois = date
else
return erreur( 'Date', date )
end
if ( tonumber( jour ) or 0 ) > 31 and ( tonumber( annee ) or 0 ) < 31 then
-- inversion du jour et de l'année
local temp = annee
annee = jour
jour = temp
end
decalage = decalage or 0
if decalage < 0 then
decalage = decalage + 2
end
args = args or {}
return fun.validationJourMoisAnnee{
jour, mois, annee,
masquerAnnee = trim( masquerAnnee ) and true or nil,
masquerMois = ( trim( masquerAnnee ) or not annee ) and trim( masquerMois ) and true or nil,
-- or nil sert juste à éviter de trainer une valeur false dans tous les tests unitaires.
}
else
return true, {}
end
end
 
 
---
-- separationJourMoisAnnee prend jusqu'a cinq paramètre et essaie de les séparer en jour, mois, annee et qualificatif
Ligne 247 ⟶ 299 :
function fun.validationJourMoisAnnee( frame, ... )
local args = Outils.extractArgs( frame, ... )
local jour, mois, numMois, annee, qualificatif, erreur
args[1]local bjour = tostring( args[1] or args['jour'] or '' )
args[2]local bmois = tostring( args[2] or args['mois'] or '' )
args[3]local bannee = tostring( args[3] or args['annee'] or args['année'] or '')
args[4] = tostring( args[4] or '' )
local function erreur( periode, valeur )
return false, Outils.erreur( periode .. ' invalide (' .. valeur .. ')' )
end
local decalage = 0
-- si pas de jour mais que args[2] est un mois on décale tout et on
-- n'affiche pas l'année
local arg1, arg2, arg3 = trim( args[1] ), trim( args[2] ), trim( args[3] )
if arg1 == nil and (fun.determinationMois( args[3] ) or arg2 and arg2:match( '[^ /][ /-].*%d%d$' ) ) then
decalage = 1
elseif arg1 == nil and arg2 == nil and arg3 and
( fun.determinationMois( args[4] ) or arg3:match( '[^ /][ /-].*%d%d$' ) ) then
decalage = 2
elseif arg1 and arg1:match( '%d%d%d$' ) then
-- l'année est dans le premier paramètre
decalage = -2
elseif not tonumber( args[3] ) and
tonumber( args[2] ) and tonumber( args[2] ) > 12 and
fun.determinationMois( args[1] )
then
-- le mois est dans le premier paramètre et l'année dans le deuxième
decalage = -1
end
-- on traite l'année
local bannee = args[3 + decalage]
if Outils.notEmpty( bannee ) then
annee = tonumber( bannee )
if annee == nil and type( bannee ) == 'string' then
-- test si l'année contient av. J.-C.
annee = string.match( string.upper( bannee ), '^(%d+)%sAV ?[Aa][Vv]%.?%s ?J[Jj][ .-]*[Cc]%.?%-?C' )
annee = tonumber( annee )
if annee then
annee = 0 - annee
elseif decalage == -2 then
return fun.separationJourMoisAnnee( bannee, decalage, args )
else
return erreur( 'Année', bannee )
Ligne 298 ⟶ 326 :
-- on traite le mois
local bmois = args[2 + decalage]
if Outils.notEmpty( bmois ) then
mois, numMois = fun.determinationMois( bmois )
Ligne 304 ⟶ 331 :
mois = fun.valideSaison( bmois )
if mois == nil then
return erreur( 'Mois', bmois )
if annee then
return erreur( 'Mois', bmois )
elseif type( dataLiens[ trim( bmois ) ] ) == 'table' then
-- le deuxième paramètre est un qualificatif, donc la date est dans le premier paramètre
local bjour = args[1 + decalage]
return fun.separationJourMoisAnnee( bjour, decalage, args )
else
return erreur( 'Mois ou qualificatif', bmois )
end
end
else
-- on traite le jour si présent
local bjour = args[1 + decalage]
if Outils.notEmpty( bjour ) then
jour = tonumber( bjour )
Ligne 330 ⟶ 347 :
return erreur( 'Jour', bjour )
elseif jour > liste_mois[numMois].nJour then
return erreur( 'Jour', bjour .. bmois' ' .. mois )
elseif jour == 29 and numMois == 2 and annee and ( math.fmod( annee, 4 ) ~= 0 ) then
-- l'année bisextile n'est pas testée pour accepter les dates juliennes.
-- l'année bisextile sur les siècles est toujours acceptée pour être compatible avec les dates juliennes.
return erreur( 'Jour', '29 février ' .. annee )
end
else
-- S'il n'y a pas de jour on regarde si la première lettre du mois est en majuscule
if mw.ustring.bmois:match( bmois, '^%u' ) then
-- oui, on passe la première lettre en majuscule
mois = ucfirst( mois )
Ligne 342 ⟶ 361 :
end
end
else
elseif decalage > -1 then
-- on teste le jour si présent
local bjour = args[1 + decalage]
if Outils.notEmpty( bjour ) then
if annee then
Ligne 356 ⟶ 375 :
jour = nil
else
return erreur( 'dateDate', 'jour seul : ' .. bjour )
end
else
return fun.separationJourMoisAnneeerreur( bjour'Jour', decalage, argsbjour )
end
end
Ligne 365 ⟶ 384 :
end
local resultat = {
-- on traite le champs optionnel
qualificatif = trim( args[4 + decalage] ) or args.qualificatif
local result = {
jour = jour,
mois = mois,
numMois = numMois,
annee = annee,
masquerAnnee = args.masquerAnnee,
qualificatif = qualificatif,
decalagemasquerMois = decalage + ( args.decalage or 0 )masquerMois,
}
return true, resultresultat
end
 
function fun.determinationDecalage( args )
local decalage = 0
-- si pas de jour mais que args[2] est un mois on décale tout et on
-- n'affiche pas l'année
local arg1, arg2, arg3 = trim( args[1] ), trim( args[2] ), trim( args[3] )
if arg1 == nil and fun.determinationMois( args[3] ) then
decalage = 1
elseif arg1 == nil and arg2 == nil and arg3 and fun.determinationMois( args[4] ) then
decalage = 2
elseif arg1 == nil and arg2 and arg2:match( '[^ ./-][ ./-]+[^ ./-]' ) then
decalage = 'D'
elseif arg1 and arg3 == nil and ( arg1:match( '[^ ./-][ ./-]+[^ ./-]' ) or arg2 == nil or arg2:match( '[^ ./-][ ./-]+[^ ./-]' ) ) then
-- l'année est dans le premier paramètre
decalage = -2
elseif not tonumber( arg3 ) and fun.determinationMois( arg1 ) then
arg2 = arg2 and arg2:gsub( '%-$', '' )
if tonumber( arg2 ) and tonumber( arg2 ) > 12 then
-- le mois est dans le premier paramètre et l'année dans le deuxième
decalage = -1
end
end
return decalage
end
 
function fun._modeleDateParam( args, decalage )
local function analyseParam( p )
-- sépare le signe moins final éventuel signifiant que le paramètre ne soit pas être affiché.
p = trim( p )
if p then
local d, s = p:match( '^%-?([^-]*)(%-?)$' )
if s == '-' then
return d, true
end
return d
end
end
local param, resultat, test, mM, mA
if decalage == 0 then
param = { trim( args[ 1 + decalage ] ), }
param[2], mM = analyseParam( args[ 2 + decalage ] )
param[3], mA = analyseParam( args[ 3 + decalage ] )
test, resultat = fun.validationJourMoisAnnee( param )
elseif decalage == -2 then
test, resultat = fun.separationJourMoisAnnee( args[1] )
elseif decalage == 'D' then
test, resultat = fun.separationJourMoisAnnee( args[2] )
mA = true
decalage = -1
else
param = { trim( args[ 1 + decalage ] ), trim( args[ 2 + decalage ] ), trim( args[ 3 + decalage ] ) }
test, resultat = fun.validationJourMoisAnnee( param )
if decalage > 0 then
mA = true
if decalage == 2 then
mM = true
end
end
end
if test then
resultat.qualificatif = trim( args[ 4 + decalage ] )
resultat.masquerAnnee = resultat.masquerAnnee or mA
resultat.masquerMois = resultat.masquerMois or mM
end
 
return test, resultat
end
 
---
Ligne 392 ⟶ 474 :
function fun.modeleDate( frame )
local args = Outils.extractArgs( frame )
local decalage = fun.determinationDecalage(args)
local test, resultat = fun._modeleDateParam( args, decalage )
-- séparation des paramètres jour, mois et année si nécessaire
local cat = ''
local test, resultat = fun.validationJourMoisAnnee( args )
if not test then
for n, v in pairs( resultat ) do
args[n] = v
end
resultat = fun._modeleDate( args )
 
if decalage ~= 0 then
decalage = ( decalage == -2 ) and 'P' or decalage
cat = '[[Catégorie:Page utilisant le modèle Date avec un décalage|' .. decalage .. ']]' -- catégorisation temporaire
end
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:Page utilisant le modèle date avec une syntaxe erronée]]'
not Outils.notEmpty( args.nocat ) then
return resultat .. '[[Catégorie:Page utilisant le modèle date avec une syntaxe erronée]]'
else
return resultat
end
end
return ( resultat or '' ) .. cat
local annee, mois, numMois, jour = resultat.annee, resultat.mois, resultat.numMois, resultat.jour
end
local decalage, qualificatif = resultat.decalage, resultat.qualificatif
 
function fun._modeleDate( args )
local annee, mois, numMois, jour = args.annee, args.mois, args.numMois, args.jour
local qualificatif = args.qualificatif
if ( annee or mois or jour ) == nil then
Ligne 488 ⟶ 581 :
if args.nolinks then
if jour == 1 then
jour = modelePremier
jour = '<abbr class="abbr" title="premier">1<sup>er</sup></abbr>'
end
wikiListe.insert( jour )
Ligne 509 ⟶ 602 :
-- le mois
if mois then
if #wikiListe == 0 and ( annee == nil or decalage > 1 ) then
return mois
end
if args.nolinks then
if decalagenot < 2args.masquerMois then
wikiListe.insert( mois )
end
Ligne 525 ⟶ 618 :
end
end
if lien or decalage == 2args.masquerMois then
-- s'il y a un lien on retire le lien affichant 'jour mois' pour ajouter '[[mois annee|mois']]
wikiListe.remove()
if decalagenot < 2args.masquerMois then
wikiListe.insert( wikiLien( lien, mois ) )
end
elseif #wikiListe > 0 then
else
-- sinon on retire le lien affichant 'jour' pour ne garder que le lien 'jour mois'
wikiListe.remove( #wikiListe - 1 )
elseif args.masquerAnnee then
-- s'il n'y avait pas je jour, la liste est vide mais ça ne pose pas de problème
-- saufs'il sin'y a pas de jour et que l'année n'est pas affichée, on insère le mois :seul.
if #wikiListe == 0 and .insert( annee == nil or decalage > 0mois ) then
return mois
end
end
end
Ligne 551 ⟶ 642 :
-- l'année
if annee then
if not args.masquerAnnee then
local texteAnnee = annee
local lientexteAnnee = annee
local lien
if annee < 0 then
localif annneeAvJcannee =< 0 - anneethen
lien = lien or ( local annneeAvJc .. '= av.0 J.-C.' )annee
local avJC lien = trim(lien or string.lower( argsannneeAvJc ..avJC or '' )av. J.-C.' )
if local avJC = trim( string.lower( args.avJC ==or 'non' then) )
if args.avJC == 'non' then
texteAnnee = annneeAvJc
texteAnnee = annneeAvJc
else
else
texteAnnee = annneeAvJc .. ' <abbr class="abbr" title="'
..texteAnnee = annneeAvJc .. ' avant<abbr Jésus-Christclass="abbr">av. J.-C.</abbr>title="'
.. annneeAvJc .. ' avant Jésus-Christ">av. J.-C.</abbr>'
end
end
if args.nolinks then -- seulement si on doit l'affichée
end
if args.nolinks then -- seulement si on doit l'affichée
if decalage < 1 then
wikiListe.insert( texteAnnee )
endelse
lien = existDate( dataQualificatif, annee ) or existDate( dataCat, annee ) or lien or annee
else
if mois and #wikiListe == 0 then
lien = existDate( dataQualificatif, annee ) or existDate( dataCat, annee ) or lien or annee
-- si le mois n'a pas de lien et n'est pas affiché avec le jour, il est affiché avec l'année.
if mois and #wikiListe == 0 then
texteAnnee = mois .. ' ' .. texteAnnee
-- si le mois n'a pas de lien et n'est pas affiché avec le jour, il est affiché avec l'année.
end
texteAnnee = mois .. ' ' .. texteAnnee
end
if decalage < 1 then -- seulement si on doit l'affichée
wikiListe.insert( wikiLien( lien, texteAnnee ) )
end
end
if gannee > 999 then
iso.insert( 1, gannee )
Ligne 638 ⟶ 726 :
:wikitext( age )
:done()
end
-- catégorisation
if decalage ~= 0 then
wikiHtml:wikitext( '[[Catégorie:Page utilisant le modèle Date avec un décalage|' .. decalage .. ']]' )
end
return tostring( wikiHtml )
end
 
 
---