Module:Date
- Cette documentation est incluse depuis Module:Date/Documentation. [rafraîchir] · [modifier] · [historique]
Attention, certaines fonctions de ce module sont utilisées par les modèles {{ouvrage}}, {{article}} et {{archives}} (100 000 pages).
Utilisation
modifierFonctions utilisables depuis un modèle
modifiermodeleDate(frame)
– affiche une date avec les liens les plus pertinents (précisions ci-dessous).modeleInscriptionDate(frame)
– affiche une date correctement formatée, sans lien. L'année est obligatoire. Paramètres nommés année, mois, jour. (utilisé par module Biblio). Étonnamment elle se trouve implémentée en réalité dans Module:Biblio/Commun.dateISO(frame)
– similaire à modeleInscriptionDate mais la date est au format aaaa-mm-jj. Paramètres nommés année, mois, jour. Pour respecter l'ISO 8601 qui définit la date uniquement selon le calendrier grégorien, cette fonction ne retourne rien pour les dates avant 1583.dateRepublicain(frame)
– affiche une date grégorienne au format républicain (sans liens). Paramètres 1=année, 2=mois, 3=jour.modeleAge(frame)
- retourne l'âge (nombre d'année) depuis une date ou entre deux dates. Paramètres 1=année, 2=mois, 3=jour, 4=année, 5=mois, 6=jour.erreurModuleData()
- retourne un message d'erreur si Module:Date/Data ne se charge pas correctement.checkDataCat(frame)
- retourne une liste de pages annuelle et mensuelle pour faciliter les mises à jour de Date/Data. Paramètres 1=cat, mois=liste de mois si 'oui', alias = liste tous les alias si 'oui'
Fonctions utilisables depuis un autre module
modifiernomDuMois( num )
– retourne le nom français du mois n°num
.valideMois( mois )
– retourne le nom français et le n° demois
(nom français, abrégé, anglais, ou nombre entre 1 et 12).determinationMois( mois, frame )
- similaire à valideMois, mais le numéro du mois n'est pas limité (14 → février), et peut même être une expression si un objet frame est fourni ( 6 + 3 → septembre )do_dayRank(arguments)
- Rang du jour dans l'année. Paramètre arguments = { année, mois, jour } ou { year = année, month = mois, day = jour }isLeapYear(year)
- retourne true si year est une année bissextile dans le calendrier grégorien.toRoman(number)
- transforme number en une chaine le représentant en « chiffres romains ».age( an, mn, jn, ac, mc, jc )
- similaire à modeleAge, mais les paramètres ne sont pas dans une tablejulianDay( year, month, day, hour, minute, second )
- retourne le jour julien de la date transmise, suivant le calendrier grégorien astronomique (avec année 0)julianDayJulian( year, month, day, hour, minute, second )
- retourne le jour julien d'une date du calendrier julien astronomique (avec année 0)julianDayToGregorian( jd )
- retourne trois variables année, mois, jour représentant la date du calendrier grégorien astronomique correspondant à ce jour julien.julianDayToJulian( jd )
- retourne trois variables année, mois, jour représentant la date du calendrier julien correspondant à ce jour julien.julianToGregorian( year, month, day )
- transforme une date du calendrier julien en date du calendrier grégorien.gregorianToJulian( year, month, day )
- transforme une date du calendrier grégorien en date du calendrier julien.
Modules externes dont ce module a besoin pour fonctionner
modifierDate/Data
- Base de donnée permettant de ne pas tester les pages que l'on sait existantes, ou n'existant pas.TableBuilder
– Utilise.insert
et.concat
pour simplifier la syntaxe.
modeleDate( frame )
modifierParamètres
modifier1
- jour ou vide - numérique, exception possible pour 1er ou Modèle:1er.2
- mois ou jour - numérique ou nom français ou anglais, éventuellement une abréviation courante.3
- année ou mois - Un nombre sera considéré comme année. Les années sont considérées comme suivant le calendrier grégorien après le 14 octobre 1582 (sauf si julien = 'oui') et le calendrier julien avant, sans année 0.4
- qualificatif ou année - texte correspondant à une page type « en photographie » pour « 2008 en photographie »5
- qualificatifage
ouâge
- non vide pour afficher l'âge (aucun âge n'est affiché pour les dates dans le futur)julien
- 'oui' pour que la date soit considérée comme suivant le calendrier julien après le 14 octobre 1582. La date grégorienne avec liens est affichée suivie de la date julienne entre parenthèses.avJC
- 'non' pour ne pas afficher 'av. J.-C.' après l'année si elle représente une année avant Jésus Christ. Utile pour éviter les répétitions.paramètres page
- Si un modèle {{date}} contient ce paramètre, les paramètresjulien
,avJC
etqualificatif
seront appliqués à toutes les dates de la page, sauf si une autre valeur de ces paramètres est indiquée. Le modèle date qui contient ce paramètre n'a pas besoin d'être affiché par le module Date, et peut être en commentaire dans la page. La page doit être purgée pour que ce paramètre soit pris en compte.qualificatif
- qualificatif à appliquer sur toute la page. Ne fonctionne qu'en liaison avec le paramètreparamètres page
Fonctionnement
modifier- le modèle cherche à afficher la date avec des liens vers les pages liées au qualificatif. S'il n'y a pas de page liée au qualificatif un lien sera fait vers la page générale.
- le premier paramètre est vide et le troisième correspond à un mois (texte uniquement), tous les paramètres sont considérés comme décalés et l'année ne sera pas affichée.
- s'il n'y a pas de page spécifique pour ce mois-année, le mois sera affiché lié avec le jour à l'éphéméride. Priorité est donnée à l'éphéméride du qualificatif sur le lien mois-année sans qualificatif.
- le modèle s'aide de la base de donnée Date/Data pour éviter d'utiliser la fonction mw.title (équivalent du parser #ifexist:).
- cette base permet de remplacer le qualificatif par une catégorie plus générique. Si le qualificatif est « en tennis », l'éphéméride et la page mensuelle sera liée au qualificatif « en sport ».
- pour éviter de répéter le même qualificatif sur toute les dates de la page, il suffit d'avoir quelque part dans le texte de la page, même en commentaire mais pas amené par un modèle, le texte
{{Date|paramètres page= |qualificatif= mon qualificatif}}
. Le modèle peut contenir d'autre paramètres. Seul le premier modèle date contenant ce paramètre sera pris en compte.
Fonction modeleDate
modifierMotif testé | Chaîne testée | Module | Fonctions coûteuses modèle d'avant / module |
---|---|---|---|
date récente | 14|octobre|2001 | 1 / 0 | |
date ancienne (1700 - 1943), jour =1 | 1|octobre|1842 | 1 / 1 | |
date très ancienne (<1700), jour = 1er | 1|janvier|537 | 1 / 0 | |
qualificatif qui n'est pas dans la base | 14|octobre|2010|en animation asiatique | 4 / 1 | |
date ancienne, qualificatif qui n'est pas dans la base | 14|octobre|1842|en animation asiatique | 4 / 2 | |
avec qualificatif | 14|Octobre|2001|en astronautique | 3 / 0 | |
avec qualificatif avec éphémérides | 14|octobre|2005|dans les chemins de fer | 4 / 0 | |
pas de jour | |octobre|2001 | 1 / 0 | |
pas de jour avec qualificatif | |Octobre|2001|en astronautique | 3 / 0 | |
qualificatif avec page annuelle qui pourrait exister | 14|octobre|2006|en Égypte | 4 / 1 | |
qualificatif avec page mensuelle existante | 14|octobre|2008|en France | 3 / 0 | |
qualificatif avec page mensuelle qui pourrait exister | 14|octobre|2012|en France | 4 / 1 | |
qualificatif avec page annuelle et mensuelle qui pourrait exister | 14|octobre|2012|en économie | 4 / 2 | |
date ancienne avec qualificatif | 14|octobre|1845|en aéronautique | 4 / 1 | |
date négative | 13|octobre|-63 | 1 / 0 | |
date av. J.-C. (orthographe de la page) | 1|octobre|63 av. J.-C. | Jour invalide (Modèle:1) | 1 / 0 |
date avJC (orthographe abrégée) | 13|octobre|63 avJC | 1 / 0 | |
date négative, paramètre pour cacher av. J.-C. | 13|octobre|-63|avJC=non | 1 / 0 | |
année invalide | 14|octobre|2001 en sport | Année invalide (2001 en sport) | 1 / 0 |
jour + mois avec majuscule | 14|Octobre|2001 | 1 / 0 | |
mois en abrégé | 14|oct.|2001 | 1 / 0 | |
mois en chiffre | 14|10|2001 | 1 / 0 | |
mois invalide | 14|otcobre|2001 | Mois invalide (otcobre) | 1 / 0 |
jour invalide | jeudi 14|octobre|2001 | 1 / 0 | |
jour invalide (trop grand pour le mois) | 31|septembre|2001 | Jour invalide (31 septembre) | 1 / 0 |
uniquement l’année | ||2001 | 1 / 0 | |
uniquement l’année avec qualificatif | ||2001|en littérature | 1 / 0 | |
sans année | 14|octobre | 0 / 0 | |
jour uniquement | 14 | 0 / 0 | |
mois uniquement | |Octobre | Octobre | 0 / 0 |
sans argument | 0 / 0 | ||
date du calendrier julien | 1|octobre|2001|julien=oui | 1er octobre 2001 ( dans le calendrier grégorien) | |
date du calendrier julien (changement de mois) | 25|octobre|2001|julien=oui | 25 octobre 2001 ( dans le calendrier grégorien) | |
date du calendrier julien (changement d'année) | 25|décembre|2001|julien=oui | 25 décembre 2001 ( dans le calendrier grégorien) | |
date de naissance | 14|octobre|2001|age=oui |
Comparaison avec {{date de naissance}}
modifier- les fonctions coûteuses sont les mêmes que celles du modèle Date
- sans l'âge, voir comparaison avec {{Date}}
Motif testé | Chaîne testée | Modèle Date de naissance | Module |
---|---|---|---|
simple | 1|8|2006|âge=oui | Modèle:Date de naissance | |
avec qualificatif | 1|août|2006|en Suisse|age=oui | Modèle:Date de naissance | |
date ancienne | 2|1|598|age=oui | Modèle:Date de naissance | |
l'an dernier | 2|1|2012|age=oui | Modèle:Date de naissance | |
cette année | 2|1|2013|age=oui | Modèle:Date de naissance | |
l'an prochain | 2|1|2014|age=oui | Modèle:Date de naissance | |
sans jour | |8|2006|âge=oui | Modèle:Date de naissance | |
annee seule | ||2006|âge=oui | Modèle:Date de naissance |
Comparaison avec {{date sport}}
modifier- lorsqu'il n'y a pas de qualificatif, « en sport » est ajouté pour tester le module.
Motif testé | Chaîne testée | Modèle Date sport | Module | Fonctions coûteuses modèle / module |
---|---|---|---|---|
simple | 1|2|1980 | Modèle:Date sport | 1 / 0 | |
avec qualificatif | 12|2|1980|en gymnastique | Modèle:Date sport | 2 / 0 | |
qualificatif avec page possible pour cette année | 12|2|1977|en gymnastique | Modèle:Date sport | 3 / 1 | |
avec qualificatif et âge | 12|2|1980|en gymnastique|age=oui | Modèle:Date sport | 2 / 0 | |
date ancienne | 12|2|1843 | Modèle:Date sport | 1 / 0 | |
date récente avec page mensuelle | 12|2|2006 | Modèle:Date sport | 1 / 0 | |
date récente avec page mensuelle et qualif | 12|2|2006|en gymnastique | Modèle:Date sport | 2 / 0 | |
date trop récente sans page mensuelle | 1|8|2013 | Modèle:Date sport | 1 / 1 | |
date trop récente sans page mensuelle et qualif avec page annuelle possible |
1|8|2013|en gymnastique | Modèle:Date sport | 3 / 2 |
local fun = {}
local Outils = require 'Module:Outils'
local Yesno = require 'Module:Yesno'
-- chargement de la base de donnée répertoriant certaines pages existant ou n'existant pas pour éviter les "ifexist".
local dataLiens
local success, resultat = pcall ( mw.loadData, 'Module:Date/Data' )
if success then
dataLiens = resultat
else
-- protection au cas ou le sous module serait mal modifié
dataLiens = { [''] = { mois = { aucun = 1000, tous = { 1773, 2014 } }, } }
end
-- nettoie un paramètre non nommé (vire les espaces au début et à la fin)
-- retourne nil si le texte est vide ou n'est pas du texte. Attention c'est important pour les fonction qui l'utilise.
local trim = Outils.trim
-- Fonction destiné à mettre la première lettre du mois en majuscule du mois :
-- utilisation de string car aucun mois ne commance par une lettre non ascii en français ou anglais.
local function ucfirst( str )
return str:sub( 1, 1 ):upper() .. str:sub( 2 )
end
local modelePremier = '<abbr class="abbr" title="premier">1<sup>er</sup></abbr>'
-- liste des mois, écriture exacte et alias, en minuscule
local listeMois = {
{ num = 1, nJour = 31, abrev = 'janv.', nom = 'janvier', alias = { 'jan.', 'janv.', 'jan', 'janv', 'january' } },
{ num = 2, nJour = 29, abrev = 'fév.', nom = 'février', alias = { 'fevrier', 'fev.', 'fev', 'fév.', 'fév', 'févr', 'févr.', 'february' } },
{ num = 3, nJour = 31, abrev = 'mars', nom = 'mars', alias = { 'mar.', 'mar', 'march' } },
{ num = 4, nJour = 30, abrev = 'avr.', nom = 'avril', alias = { 'avr.', 'avr', 'apr', 'april'} },
{ num = 5, nJour = 31, abrev = 'mai', nom = 'mai', alias = { 'may' } },
{ num = 6, nJour = 30, abrev = 'juin', nom = 'juin', alias = { 'jun', 'june' } },
{ num = 7, nJour = 31, abrev = 'juill.', nom = 'juillet', alias = { 'juil.', 'juil', 'juill.', 'juill', 'jul', 'july' } },
{ num = 8, nJour = 31, abrev = 'août', nom = 'août', alias = { 'aoû', 'aug', 'august' } },
{ num = 9, nJour = 30, abrev = 'sept.', nom = 'septembre', alias = { 'sept.', 'sept', 'sep.', 'sep', 'september' } },
{ num = 10, nJour = 31, abrev = 'oct.', nom = 'octobre', alias = { 'oct.', 'oct', 'october' } },
{ num = 11, nJour = 30, abrev = 'nov.', nom = 'novembre', alias = { 'nov.', 'nov', 'november' } },
{ num = 12, nJour = 31, abrev = 'déc.', nom = 'décembre', alias = { 'decembre', 'déc.', 'dec.', 'dec', 'déc', 'december' } },
aout = { num = 8, nJour = 31, abrev = 'aout', nom = 'aout', alias = { 'aou' } },
}
-- ajoute les noms, abreviations et alias en tant que clé de listeMois
for i = 1, 12 do
local mois = listeMois[ i ]
listeMois[ tostring( i ) ] = mois
listeMois[ '0' .. i ] = mois
listeMois[ mois.nom ] = mois
listeMois[ mois.abrev ] = mois
for _, n in ipairs( mois.alias ) do
listeMois[ n ] = mois
end
end
for _, n in ipairs( listeMois.aout.alias ) do
listeMois[ n ] = listeMois.aout
end
fun.listeMois = listeMois
local liste_saisons = {
{ 'printemps', 'spring', },
{ 'été', 'summer', },
{ 'automne', 'autumn', },
{ 'hiver', 'winter', },
}
-- nom du mois à partir du numéro
function fun.nomDuMois( num )
if type( num ) ~= "number" or num < 1 or num > 12 then
return nil
end
return listeMois[num].nom
end
---
-- valide que la chaîne passée est un mois valide.
-- retourne le nom complet ou nil si non reconnu
-- si reconnu, retourne aussi le numéro du mois [1-12]
function fun.valideMois( mois )
local m = trim( mois )
if m then
m = mw.ustring.lower( m )
if listeMois[ m ] then
return listeMois[ m ].nom, listeMois[ m ].num
end
end
end
---
-- valide que la chaîne passée est une saison valide.
-- retourne le nom complet ou nil si non reconnu
function fun.valideSaison( saison )
local s = trim( saison )
if s then
s = mw.ustring.lower( s )
for i = 1, 4 do
for _, n in ipairs( liste_saisons[i] ) do
if s == n then
return liste_saisons[i][1]
end
end
end
end
end
---
-- determinationMois trouve le numéro du mois et son nom,
-- à partir de son nom, de son numéro ou d'une expression mathématique.
-- Si le deuxième paramètre est vrai, les nombres supérieur à 12 ou non entiers sont acceptés.
function fun.determinationMois( mois, mod, boucle )
local num, nom
if tonumber( mois ) then
num = math.floor( tonumber( mois ) )
if mod then
-- si le nombre du mois est calculé par une exression, le résultat peut être supérieur à 12, ou inférieur à 1
num = math.fmod( num + 239, 12 ) + 1 -- +239 car fmod(-1) = -1 et non 11
elseif num < 1 or num > 12 then
num = nil
end
elseif trim( mois ) then
nom, num = fun.valideMois( mois )
if nom == nil and boucle == nil then
-- essai de détermination d'un nombre avec le parser #expr de Mediawiki.
-- le paramètre boucle évite de tourner en boucle.
nom, num = fun.determinationMois( mw.getCurrentFrame():callParserFunction( '#expr', mois ), true, true )
end
end
if num and not nom then
nom = listeMois[ num ].nom
end
return nom, num
end
-- fonction interne à modeleDate, pour déterminer si on peut se passer de faire un ifexit
local function existDate( dataQualificatif, annee, mois )
local data
if mois then
data = dataQualificatif.mois
else
data = dataQualificatif.annee
end
if type( data ) ~= 'table' then
-- si data n'existe pas c'est que l'on considère qu'il n'y a pas de lien.
return
end
-- le qualificatif est remplacer par celui de la base de donnée, ce qui permet des alias.
local lien = annee .. ' ' .. ( dataQualificatif.qualificatif or '' )
local seul = annee
if mois then
lien = mois .. ' ' .. lien
seul = ucfirst( mois ) .. ' ' .. annee
end
local aucun = tonumber( data.aucun )
if aucun and annee <= aucun then
-- si la l'année est dans la partie 'aucun' on teste s'il y a malgré tout un lien isolé
if type( data.seul ) == 'table' then
for i, v in ipairs( data.seul ) do
if seul == v or seul == tonumber( v ) then
return lien
end
end
end
-- partie aucun et pas de lien => nil
return nil
elseif type( data.tous ) == 'table' then
local tous1, tous2 = tonumber( data.tous[1] ), tonumber( data.tous[2] )
if tous1 and tous2 and annee >= tous1 and annee <= tous2 then
-- l'année est dans la partie 'tous' donc on retourne le lien
return lien
end
end
-- l'annee n'est ni dans la partie aucun, ni dans la partie tous donc il faut tester si la page existe.
local cibleLien = mw.title.new( lien )
if cibleLien and cibleLien.exists then
return lien
end
end
---
-- Supprime le jour de la semaine, et "le" avant une date
function fun.nettoyageJour( jour )
if type( jour ) == 'string' then
local nomJour = { '[Ll]undi', '[Mm]ardi', '[Mm]ercredi', '[Jj]eudi', '[Vv]endredi',
'[Ss]amedi', '[Dd]imanche', '^ *[Ll]e' }
local premier = { '<abbr class="abbr" title="[Pp]remier" ?>1<sup>er</sup></abbr>', '1<sup>er</sup>', '1er' }
for i, v in ipairs( nomJour ) do
jour = jour:gsub( v, '' )
end
for i, v in ipairs( premier ) do
jour = jour:gsub( v, '1' )
end
jour = trim( jour )
end
return jour
end
---
-- Sépare une chaine date en un table contenant les champs jour, mois et annee.
-- la date doit contenir le mois.
function fun.separationJourMoisAnnee( date )
date = trim( date )
if date then
local function erreur( periode, valeur )
return false, Outils.erreur( periode .. ' invalide (' .. valeur .. ')' )
end
local jour, mois, annee, masquerMois, masquerAnnee, separateur
-- variable pour construire les regex
local j = '([0-3]?%d)' -- jour
local m = '([01]?%d)' -- mois numérique
local mmm = '([^%s%p%d]+[.]?)' -- mois en toute lettre
local aj = '(%-?%d+)' -- année ou jour
local s = '[ ./-]+' -- séparateur simple
local sep = '([ ./-]+)' -- séparateur avec capture, pour le détecter deux fois
local 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 )
-- suppression catégorie, liens, balises
date = mw.ustring.gsub( date, '%[%[[Cc]at[ée]gor[yi]e?:.-%]%]', '' )
date = date :gsub( '%b<>', '' )
:gsub( '%[%[([^%[%]|]*)|?([^%[%]]*)%]%]', function ( l, t ) return trim( t ) or l end )
-- suppression des espaces insécables
:gsub( '\194\160', ' ' )
:gsub( ' ', ' ' )
:gsub( '\226\128\175', ' ' )
:gsub( '&nnbsp;', ' ' )
:gsub( '\226\128\137', ' ' )
:gsub( ' ', ' ' )
:gsub( ' ', ' ' )
:gsub( ' +', ' ' )
-- réduction av. J-C pour simplifier un peu les regex :
:gsub( '(%d+) ?[Aa][Vv]%.? ?[Jj][ .-]*[Cc]%.?', '-%1' )
-- supression de l'heure dans les date ISO
:gsub( '^+?([%d-]*%d%d%-%d%d)T%d%d[%d:,.+-]*Z?$' , '%1')
-- test année seule
if date:match( '^'..aj..'$' ) then
annee = date:match( '^'..aj..'$' )
elseif date:match( '^'..aj..s..aj..moins..'$' ) then
-- jj/mm, mm/aaaa ou aaaa/mm
local a, separateur, b, sb = date:match( '^'..aj..sep..aj..moins..'$' )
a, b = tonumber( a ), tonumber( b )
if separateur: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 erreur( 'Date', date )
elseif b < 1 or b > 31 then
mois, annee, masquerAnnee = a, b, sb
elseif a < 1 or a > 31 then
annee, mois = a, b
elseif b > 12 then
return erreur( 'Mois', b )
else
jour, mois, masquerMois = a, b, sb
end
elseif date:match( '^'..aj..sep..m..moins..'%2'..aj..moins..'$' ) then
-- jj/mm/aaaa ou aaaa/mm/jj
jour, separateur, mois, masquerMois, annee, masquerAnnee = date:match( '^'..aj..sep..m..moins..'%2'..aj..moins..'$' )
if separateur == '-' 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, separateur, mois, masquerMois, annee, masquerAnnee = date:match( '^'..j..sep..mmm..moins..'%2'..aj..moins..'$' )
elseif date:match( '^'..mmm..s..aj..moins..'$' ) then
-- mmm aaaa
mois, separateur, annee, masquerAnnee = date:match( '^'..mmm..sep..aj..moins..'$' )
if separateur:match( '^.+%-$' ) then
annee = '-' .. annee
end
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
local jn, an = tonumber( jour ), tonumber( annee )
if jn and an and ( jn > 31 or jn < 0 or #jour >= 3 ) and an <= 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 = annee
annee = jour
jour = temp
end
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
---
-- validationJourMoisAnnee vérifie les paramètres correspondent à une date valide.
-- la date peut être dans les paramètre 1 à 3, ou dans des paramètres jour, mois et annee.
-- La fonction retourne true suivit d'une table avec la date en paramètres nommé (sans accent sur année)
-- ou false suivit d'un message d'erreur.
function fun.validationJourMoisAnnee( frame, ... )
local args = Outils.extractArgs( frame, ... )
local jour, mois, numMois, annee
local bjour = args[1] or args['jour'] or ''
local bmois = tostring( args[2] or args['mois'] or '' )
local bannee = args[3] or args['annee'] or args['année'] or ''
local function erreur( periode, valeur )
return false, Outils.erreur( periode .. ' invalide (' .. valeur .. ')' )
end
-- on traite l'année
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+) ?[Aa][Vv]%.? ?[Jj][ .-]*[Cc]%.?' )
annee = tonumber( annee )
if annee then
annee = 0 - annee
else
return erreur( 'Année', bannee )
end
elseif annee == 0 then
return erreur( 'Année', 0 )
end
else
annee = nil
end
-- on traite le mois
if Outils.notEmpty( bmois ) then
mois, numMois = fun.determinationMois( bmois )
if mois == nil then
mois = fun.valideSaison( bmois )
if mois == nil then
return erreur( 'Mois', bmois )
end
else
-- on traite le jour si présent
if Outils.notEmpty( bjour ) then
jour = tonumber( bjour )
if jour == nil then
jour = tonumber( fun.nettoyageJour( bjour ) )
end
if jour == nil then
return erreur( 'Jour', bjour )
end
-- on valide que le jour est correct
if jour < 1 or jour > 31 then
return erreur( 'Jour', bjour )
elseif jour > listeMois[numMois].nJour then
return erreur( 'Jour', bjour .. ' ' .. mois )
elseif jour == 29 and numMois == 2 and annee and ( math.fmod( annee, 4 ) ~= 0 ) then
-- 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 bmois:match( '^%u' ) then
-- oui, on passe la première lettre en majuscule
mois = ucfirst( mois )
end
-- s'il n'y a pas d'année non plus on retourne le mois simple
end
end
else
-- on teste le jour si présent
if Outils.notEmpty( bjour ) then
if annee then
return erreur( 'Mois', 'absent' )
else
bjour = fun.nettoyageJour( bjour )
jour = tonumber( bjour )
if jour then
if jour > 31 or jour < 1 then
annee = jour
jour = nil
else
return erreur( 'Date', 'jour seul : ' .. bjour )
end
else
return erreur( 'Jour', bjour )
end
end
end
end
-- vérification de l'absence d'un décalage
if annee and annee < 13 and annee > 0 and not jour and ( tonumber( bmois ) or (not mois and tonumber( args[4] ) ) ) then
return false, Outils.erreur( 'année improbable (' .. annee .. ')' )
end
local resultat = {
jour = jour,
mois = mois,
numMois = numMois,
annee = annee,
masquerAnnee = args.masquerAnnee,
masquerMois = args.masquerMois,
}
return true, resultat
end
---
-- émule le modèle {{m|Date}}.
-- Paramètres :
-- 1 : jour (numéro ou "1er") ou la date complète
-- 2 : mois (en toutes lettres) ou spécialité de l'année
-- 3 : année (nombre)
-- 4 : spécialité de l'année
-- julien : date dans le calendrier julien
-- compact : affiche le mois sous forme d'abréviation
-- avJC : non pour désactiver l'affichage de « av. J.-C. » pour les date négatives
-- âge : ajout la durée depuis cette date
-- nolink : ne met pas de lien sur la date
-- naissance : ajoute la class "bday"
-- mort : ajoute la class "dday"
function fun.modeleDate( frame )
local args = Outils.extractArgs( frame )
local cat, resultat = ''
-- analyse des paramètres non nommés (ou paramètres de la date jour, mois, annee)
local test, params
local arg1, arg2, arg3 = fun.nettoyageJour( args[1] ), trim( args[2] ), trim( args[3] )
if type( arg1 ) == 'string' and arg3 == nil and ( arg1:match( '[^ ./-][ ./-]+[^ ./-]' ) or arg2 == nil or dataLiens[arg2] or mw.ustring.match( arg2, '%a %a' ) ) then
-- la date est dans le premier paramètre
test, params = fun.separationJourMoisAnnee( arg1 )
if test then
params.qualificatif = arg2
end
else
local function masquerParam( p )
-- sépare le signe moins final éventuel signifiant que le paramètre ne doit pas être affiché.
if type( p ) ~= 'string' then
return p, nil
end
local value, mask = p:match( '^%s*(.-)(%-?)%s*$' )
return value, ( mask == '-' or nil )
end
local cleanArgs = { arg1 or args.jour }
cleanArgs[2], cleanArgs.masquerMois = masquerParam( args[2] or args.mois )
cleanArgs[3], cleanArgs.masquerAnnee = masquerParam( args[3] or args.annee or args['annee'] )
mw.logObject( cleanArgs )
test, params = fun.validationJourMoisAnnee( cleanArgs )
if test then
params.qualificatif = trim( args[4] )
end
end
-- analyse des paramètres nommés
if test then
params.qualificatif = params.qualificatif or args.qualificatif
-- julien peut avoir trois valeurs: inactif, format standard (true), format court
params.julien = Yesno( args.julien, 'court', false )
params.avJC = Yesno( args.avJC )
local listeParam = {
age = 'âge',
['âge'] = 'âge',
naissance = 'naissance',
mort = 'mort',
['décès'] = 'mort',
nolinks = 'nolinks',
compact = 'compact',
compacte = 'compact',
}
for n, v in pairs( listeParam ) do
params[v] = params[v] or Yesno( args[n], true, false ) or nil
end
-- sortie pour les tests unitaire, ou pour débuger
if args.debug then
return params
end
resultat = fun._modeleDate( params )
else
local namespaceCategorisation = { [0] = true, [4] = true, [10] = true, [14] = true, [100] = true }
if namespaceCategorisation[ mw.title.getCurrentTitle().namespace ] and not Outils.notEmpty( args.nocat ) then
cat = '[[Catégorie:Page utilisant le modèle date avec une syntaxe erronée]]'
end
resultat = params .. cat
end
return resultat or ''
end
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
return
end
-- on traite l'age, naissance et mort
local age = args['âge'] and fun.age( annee, numMois, jour )
local naissance = args.naissance
local mort = args.mort
-- on traite le calendrier
local gannee, gmois, gjour = annee, numMois, jour -- date suivant le calendrier grégorien pour time
local jannee, jmois, jjour = annee, mois, jour -- date suivant le calendrier julien si necessaire
local julien, julien2, julien3, julien4 -- servira éventuellement à a afficher la date selon le calendrier julien
if annee and jour then
local amj = annee * 10000 + numMois * 100 + jour
if amj < 15821014 then
if annee > 0 then
gannee, gmois, gjour = fun.julianToGregorian( annee, numMois, jour )
else
-- calendrier grégorien proleptique avec année 0.
gannee, gmois, gjour = fun.julianToGregorian( annee + 1, numMois, jour )
end
args.julien = false
elseif args.julien then
gannee, gmois, gjour = fun.julianToGregorian( annee, numMois, jour )
annee, mois, jour = gannee, listeMois[gmois].nom, gjour
if jjour == 1 then
jjour = modelePremier
end
if args.compact then
jmois = listeMois[ jmois ].abrev
end
julien = mw.html.create( '' )
if args.julien == 'court' then
julien = julien:tag( 'span')
:addClass( 'nowrap' )
:wikitext( jjour, ' ', jmois, ' ' )
if jannee == annee then
julien2 = '<sup>[[calendrier grégorien|grég.]]</sup>'
else
julien:wikitext( jannee, ' ' )
julien3 = '<sup>[[calendrier grégorien|grég.]]</sup>'
end
julien = julien:tag( 'sup' )
:wikitext( '[[calendrier julien|jul.]]' )
:allDone()
:wikitext( ' / ' )
else
julien:tag( 'span')
:addClass( 'nowrap' )
:wikitext( jjour, ' ', jmois, ' ', jannee )
:done()
:wikitext( ' (' )
julien4 = ' [[Passage du calendrier julien au calendrier grégorien|dans le calendrier grégorien]])'
end
end
else
if annee and annee < 0 then
gannee = gannee + 1
end
args.julien = false
end
-- on génère le résultat
-- Déclarations des variables
local wikiListe = {} -- reçois le texte affiché pour chaque paramètre
local iso = {} -- reçois le format date ISO de ce paramètre
local texteMois = mois -- texte du mois qui sera affiché (éventuellement l'abréviation)
if args.compact then
if args.nolinks then
texteMois = '<abbr class=abbr title="' .. mois .. '">' .. listeMois[ mois ].abrev .. '</abbr>'
else
texteMois = listeMois[ mois ].abrev
end
end
mois = mois and mois:gsub( 'aout', 'août' )
local dataQualificatif, dataCat
if not args.nolinks then
dataQualificatif = dataLiens[qualificatif or '']
if type( dataQualificatif ) ~= 'table' then
-- si le qualifiquatif n'est pas dans la base de donnée, on crée une table minimum,
-- qui imposera un test sur l'annee, mais considère qu'il n'y a pas de lien sur le jour ou le mois
dataQualificatif = { qualificatif = ' ' .. qualificatif, annee = { } }
end
dataCat = dataLiens[dataQualificatif.cat]
if type( dataCat ) ~= 'table' or dataCat == dataQualificatif then
dataCat = { qualificatif = '' }
end
end
local function wikiLien( lien, texte )
if lien == texte then
return '[[' .. texte .. ']]'
else
return '[[' .. lien .. '|' .. texte .. ']]'
end
end
-- le jour si présent
local qualifJour = ''
if jour then
local texteJour = jour
if args.nolinks then
if jour == 1 then
jour = modelePremier
end
table.insert( wikiListe, jour )
else
qualifJour = dataQualificatif.jour and dataQualificatif.qualificatif
or dataCat.jour and dataCat.qualificatif
or ''
local lien = jour .. ' ' .. mois .. ' ' .. qualifJour
if jour == 1 then
jour = '1<sup>er</sup>'
lien = '1er ' .. mois .. ' ' .. qualifJour
end
-- s'il n'y a pas de lien sur le mois, il sera affiché avec le jour.
table.insert( wikiListe, wikiLien( lien, jour ) )
table.insert( wikiListe, wikiLien( lien, jour .. ' '.. texteMois ) )
end
table.insert( iso, 1, string.sub( '0' .. gjour, -2 ) )
end
-- le mois
if mois then
if #wikiListe == 0 and annee == nil then
return texteMois
end
if args.nolinks then
if not args.masquerMois then
table.insert( wikiListe, texteMois )
end
else
local lien
if annee then
lien = existDate( dataQualificatif, annee, mois ) or existDate( dataCat, annee, mois )
if lien == nil and qualificatif and qualifJour == '' then
-- test nouveau test sans le qualificatif uniquement s'il n'y a pas d'éphémérides pour ce qualificatif.
lien = existDate( dataLiens[''], annee, mois )
end
end
if lien or args.masquerMois then
-- s'il y a un lien on retire le lien affichant 'jour mois' pour ajouter '[[mois annee|mois']]
table.remove( wikiListe )
if not args.masquerMois then
table.insert( wikiListe, wikiLien( lien, texteMois ) )
end
elseif #wikiListe > 0 then
-- sinon on retire le lien affichant 'jour' pour ne garder que le lien 'jour mois'
table.remove( wikiListe, #wikiListe - 1 )
elseif args.masquerAnnee 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( wikiListe, texteMois )
end
end
if gmois then
table.insert( iso, 1, string.sub( '0' .. gmois, -2 ) )
end
table.insert( wikiListe, julien2 )
end
-- l'année
if annee and not (args.julien == true and args.nolinks and jannee == annee ) then
if not args.masquerAnnee then
local texteAnnee = annee
local lien
if annee < 0 then
local annneeAvJc = 0 - annee
lien = lien or ( annneeAvJc .. ' av. J.-C.' )
if args.avJC == false then
texteAnnee = annneeAvJc
else
texteAnnee = annneeAvJc .. ' <abbr class="abbr" title="'
.. annneeAvJc .. ' avant Jésus-Christ">av. J.-C.</abbr>'
end
end
if args.nolinks then -- seulement si on doit l'affichée
table.insert( wikiListe, texteAnnee )
else
lien = existDate( dataQualificatif, annee ) or existDate( dataCat, annee ) or lien or annee
if mois and #wikiListe == 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.
texteAnnee = texteMois .. ' ' .. texteAnnee
end
table.insert( wikiListe, wikiLien( lien, texteAnnee ) )
end
end
if gannee > 999 then
table.insert( iso, 1, gannee )
elseif gannee > -1 then
table.insert( iso, 1, string.sub( '000' .. gannee , -4 ) )
elseif gannee > -999 then
-- calendrier grégorien proleptique avec année 0.
table.insert( iso, 1, 'U-' .. string.sub( '000' .. ( 0 - gannee ), -4 ) )
else
table.insert( iso, 1, 'U' .. gannee )
end
end
table.insert( wikiListe, julien3 )
-- l'age
if type( age ) == 'number' and age >= 0 and ( not naissance or age < 120 ) then
if age == 0 then
age = '(moins d’un an)'
elseif age == 1 then
age = '(1 an)'
else
age = '(' .. age .. ' ans)'
end
else
age = false
end
-- compilation du résultat
local wikiTexte = table.concat( wikiListe, ' ' )
local isoTexte = table.concat( iso, '-' )
-- On ajoute un peu de sémantique.
local wikiHtml = mw.html.create( '' )
:node(julien)
local dateHtml = wikiHtml:tag( 'time' )
:wikitext( wikiTexte )
if wikiTexte:match( ' ' ) then
dateHtml:addClass( 'nowrap' )
end
if isoTexte ~= wikiTexte then
dateHtml:attr( 'datetime', isoTexte )
end
if not args.nolinks then
dateHtml:addClass( 'date-lien' )
end
if naissance then
dateHtml:addClass( 'bday' )
elseif mort then
dateHtml:addClass( 'dday' )
end
wikiHtml:wikitext( julien4 )
if age then
wikiHtml:wikitext( ' ' )
:tag( 'span' )
:addClass( 'noprint')
:wikitext( age )
:done()
end
return tostring( wikiHtml )
end
---
-- fonction destinée aux infobox, notamment pour afficher les dates de naissance et de mort
-- les liens présent dans les dates fournies sont automatiquement supprimées pour gérer les cas ou
-- le paramètre contient déjà un modèle date.
-- Paramètres :
-- 1 : type de date à afficher (naissance / n, mort / m, ou date / d)
-- 1 : Date ou date de naissance
-- 2 : Date de mort si type n ou m
-- qualificatif = suffixe des page de date à lier (exemple : en musique)
-- nolinks : n'affiche pas de lien
-- préfixe : préfixe à afficher s'il y a un jour (par défaut '')
-- préfixe sans jour : préfixe à afficher s'il n'y a pas de jour (par défaut : '')
function fun.dateInfobox( frame )
local args = frame.args
if type( args ) ~= 'table' or not ( args[1] and args[2] ) then
return
end
-- analyseDate sépare la date du contenu qui suit, supprime les liens, et retourne si possible un table avec jour mois année
local function analyseDate( d )
if trim( d ) then
local analyse = d:match( ' ou ') or d:match( 'entre ' ) or d:match( 'vers ' ) or d:match( 'après ' ) or d:match( 'avant ' )
if analyse then
return d
end
analyse = d:match( 'datetime="([%d-]+)"' ) or d
-- sépare la date (avec ses liens) d'une référence ou contenu commençant par un espace)
local debut, fin = analyse:match( '(.-%d%d%d%]*%-?)([\127 ].+)' )
if not debut then
-- sépare la date du contenu commençant par <br>
debut, fin = analyse:match( '(.-%d%d%d%]*%-?)(<br ?/?>.+)' )
end
analyse = debut or analyse
-- supprime les lien
analyse = analyse:gsub(
'%[%[([^%[%]|]*)|?([^%[%]]*)%]%]',
function ( l, t )
return trim( t ) or l
end
)
local t, r = fun.separationJourMoisAnnee( analyse )
if t then
return r, fin
else
return d, fin
end
end
end
-- prefix ajoute un préfixe en fonction de la présence ou non du jour si le paramètre "préfixe sans jour" est défini
local function prefix( dateString )
if dateString then
local datetime = dateString:match( 'datetime="([U%d%-]+)"' )
if datetime and datetime:match('%-%d%d%-%d%d') and trim( args['préfixe'] ) then
return args['préfixe'] .. ' ' .. dateString
end
if trim( args['préfixe sans jour'] ) then
return args['préfixe sans jour'] .. ' ' .. dateString
end
end
return dateString
end
local naissance = args[1]:match( '^n' ) == 'n'
local mort = args[1]:match( '^m' ) or args[1]:match( 'décès' )
local affichageDate, qualificatif = args[2], args[4]
local affichageDateTab, resultatDate, complementDate
local dateNaissance, dateMort
if mort then
affichageDate = args[3]
end
if not trim( affichageDate ) then
return
end
if affichageDate: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 ( naissance or mort ) and ( affichageDate:match( 'wikidata%-linkback' )) then
dateNaissance = analyseDate( args[2] )
dateMort = analyseDate( args[3] )
resultatDate = affichageDate
else
return prefix( affichageDate )
end
else
affichageDateTab, complementDate = analyseDate( affichageDate )
if type( affichageDateTab ) ~= 'table' then
return affichageDateTab
else
if naissance then
dateNaissance = affichageDateTab
dateMort = analyseDate( args[3] )
elseif mort then
dateNaissance = analyseDate( args[2] )
dateMort = affichageDateTab
else
qualificatif = args[3]
end
affichageDateTab.naissance = naissance
affichageDateTab.mort = mort
affichageDateTab.qualificatif = args.qualificatif or qualificatif
affichageDateTab.nolinks = args.nolinks
affichageDateTab.nocat = args.nocat
affichageDateTab.julien = args.julien
end
end
resultatDate = resultatDate or fun.modeleDate( affichageDateTab )
local age, prefixAge, suffixAge, calculAge = '', ' <span class="noprint">(', ')</span>', nil
if naissance and
dateNaissance and
not dateMort and
type( dateNaissance ) == 'table'
then
calculAge = fun.age( dateNaissance.annee, dateNaissance.numMois, dateNaissance.jour )
if calculAge and calculAge > 120 then
calculAge = nil
end
elseif mort and
dateNaissance and
dateMort and
type( dateNaissance ) == 'table'
and type( dateMort ) == 'table'
then
calculAge = fun.age(
dateNaissance.annee,
dateNaissance.numMois,
dateNaissance.jour,
dateMort.annee,
dateMort.numMois,
dateMort.jour
)
prefixAge = ' (à '
suffixAge = ')'
end
if tonumber( calculAge ) then
if calculAge > 1 then
age = prefixAge .. calculAge .. ' ans' .. suffixAge
elseif calculAge == 1 then
age = prefixAge .. 'un an' .. suffixAge
elseif calculAge == 0 then
age = prefixAge .. 'moins d’un an' .. suffixAge
end
if complementDate and complementDate:match( 'ans?%)' ) then
complementDate = ''
end
end
return prefix( resultatDate ) .. ( complementDate or '' ) .. age
end
---
-- la fonction dateISO renvoie un date au format aaaa-mm-jj (sans liens)
-- l'année peut être sous la forme 2013 ou [[2013 en litérature|2013]]
-- le mois peut être en lettre ou en chiffres
-- le jour peut être sous la forme '05', '{{1er}}' ou 'vendredi 13'
function fun.dateISO( frame )
local args = Outils.extractArgs( frame )
local annee = Outils.notEmpty( args['année'], args.annee, args.year, args.date )
-- extraction de l'année
if type( annee ) == 'string' then
annee = ( tonumber( annee ) -- match '2013'
or string.match ( annee, '%D(%d%d%d%d)%D' ) -- match '[[2013 en musique|2013]]'
or string.match ( annee, '%D(%d%d%d%d)$' ) -- match '17 septembre 2013'
or string.match ( annee, '^(%d%d%d%d)%D' ) -- match '2013-09-17'
)
end
annee = tonumber( annee )
-- 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 annee and annee > 1582 then
local mois = Outils.notEmpty( args.mois, args.month )
-- num mois trouve le numéro du mois, qu'il soit numérique ou texte, complet ou abrégé.
local nomMois, numMois = fun.determinationMois( mois )
if numMois then
mois = '-' .. string.sub( '0' .. numMois, -2 )
local jour = Outils.notEmpty( args.jour, args.day, args['quantième'] )
if type( jour ) == 'string' then
jour = tonumber( jour ) or tonumber( string.match ( jour, '%d+') )
end
jour = tonumber( jour )
if jour and jour <= listeMois[numMois].nJour then
jour = '-' .. string.sub( '0' .. jour, -2 )
return annee .. mois .. jour
else
return annee .. mois
end
else
return tostring( annee )
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.dateRepublicain(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émiaire","Brumaire","Frimaire","Nivôse","Pluviôse","Ventôse","Germinal","Floréal","Prairial","Messidor","Thermidor","Fructidor"}
local extras = {"de la vertu","du génie","du travail","des récompenses","de l'opinion","de la révolution"}
local result = ""
if(arguments[2] < 13) then
result = result .. tostring(arguments[3]) .. " " .. months[arguments[2]]
else
result = result .. "jour " .. extras[arguments[3]]
end
result = result .. " de l'an " .. fun.toRoman(arguments[1])
return result
end
---
-- Voir Modèle:Âge
-- retourne l'age en fonction de la ou les dates fournies. La valeur retounée est de type 'number'
-- Parammètres :
-- 1, 2, 3 : année, mois jour de naissance (supposé dans le calendrier grégorien)
-- 4, 5, 6 : année, mois, joue du calcul (facultatif, par défaut la date UTC courante).
function fun.age( an, mn, jn, ac, mc, jc )
if ac == nil then
local today = os.date( '!*t' )
ac = today.year
mc = today.month
jc = today.day
else
ac = tonumber( ac )
mc = tonumber( mc )
jc = tonumber( jc )
end
local an = tonumber( an )
local mn = tonumber( mn )
local jn = tonumber( jn )
if an == 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 age = ac - an
if mc == mn then
if jc == nil or jn == nil then
return
end
return age-tonumber( jc < jn and 1 or 0 )
else
return age-tonumber( mc < mn and 1 or 0 )
end
end
function fun.modeleAge( frame )
local args = frame.getParent().args
local age = fun.age (
args[1] or args['année'],
args[2] or args['mois'],
args[3] or args['jour'],
args[4],
args[5],
args[6]
)
if age then
return age
else
return Outils.erreur("Paramètres incorrects ou insuffisants ou pour calculer l'âge précis" )
end
end
---
-- calcul du jour julien à partir d'une date du calendrier grégorien
function fun.julianDay( year, month, day, hour, min, sec )
local julian
julian = math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) * 1461 / 4 )
- math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) / 100 )
+ math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) / 400 )
+ math.floor( ( math.fmod( month + 57609, 12 ) + 4 ) * 153 / 5 )
+ day + ( hour or 12 ) / 24 + ( min or 0 ) / 1440 + ( sec or 0 ) / 86400
- 32167.5
return julian
end
---
-- calcul du jour julien à partir d'une date du calendrier julien
function fun.julianDayJulian( year, month, day, hour, min, sec )
local julian
julian = math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) * 1461 / 4 )
+ math.floor( ( math.fmod( month + 57609, 12 ) + 4 ) * 153 / 5 )
+ day + ( hour or 12 ) / 24 + ( min or 0 ) / 1440 + ( sec or 0 ) / 86400
- 32205.5
return julian
end
---
-- calcul d'une date dans le calendrier grégorien à partir du jour julien
function fun.julianDayToGregorian( julianDay )
local base = math.floor( julianDay + 32044.5 ) -- 1 March -4800 (proleptic Gregorian date)
local nCentury = math.floor( ( base * 4 + 3 ) / 146097 )
local sinceCentury = base - math.floor( nCentury * 146097 / 4 )
local nYear = math.floor( ( sinceCentury * 4 + 3 ) / 1461 )
local sinceYear = sinceCentury - math.floor( nYear * 1461 / 4 )
local nMonth = math.floor( ( sinceYear * 5 + 2 ) / 153 )
local day = sinceYear - math.floor( ( nMonth * 153 + 2 ) / 5 ) + 1
local month = nMonth - math.floor( nMonth / 10 ) * 12 + 3
local year = math.floor( sinceYear / 306 ) + nYear + 100 * nCentury - 4800
return year, month, day
end
---
-- calcul d'une date dans le calendrier julien à partir du jour julien
-- calcul basé sur l'algorythme de la page fr.wikipedia.org/wiki/Jour_julien (1/10/2013)
function fun.julianDayToJulian( julianDay )
local year = math.modf( ( julianDay * 4 - 6884469 ) / 1461 )
local r2 = julianDay - math.modf( ( 1461 * year + 6884472 ) / 4 )
local month = math.modf( ( 5 * r2 + 461 ) / 153 )
local day = r2 - math.modf( ( 153 * month - 457 ) / 5 ) + 1
if month > 12 then
year = year + 1
month = month - 12
end
return year, month, day
end
---
-- calcul d'une date dans le calendrier grégorien à partir d'une date dans le calendrier julien
function fun.julianToGregorian( year, month, day )
return fun.julianDayToGregorian( fun.julianDayJulian( year, month, day ) )
end
---
-- calcul d'une date dans le calendrier julien à partir d'une date dans le calendrier grégorien
function fun.gregorianToJulian( year, month, day )
year = tonumber(year)
if month then month = tonumber(month) else month = 6 end --prend une valeur centrale pour donner un best "guess"
if day then day = tonumber(day) else day = 15 end
return fun.julianDayToJulian( fun.julianDay( year, month, day ) )
end
---
-- erreurModuleData affiche d'un message d'erreur si le Module:Langue/Data n'a pas été chargé correctement,
-- pour la page de discussion de la base de donnée et ceux qui veulent surveiller cette page.
function fun.erreurModuleData()
local success, resultat = pcall ( mw.loadData, 'Module:Date/Data' )
if success == false then
local message = [[<strong class="error">Le chargement du module Date/Data génère une erreur : </strong><br />%s<br />
<span class="error">Cette erreur doit être corrigée au plus vite car des milliers de page ne s'affichent pas correctement</span>
]]
return string.format( message, resultat )
end
end
---
-- checkDataCat génère des liens vers les pages annuelles, mensuelles et d'éphémérides liè aux
-- catégories du Module:Date/Data. La date la plus ancienne dépend de 'aucun' et 'seul[1]'
-- Paramètres :
-- 1 : la catégorie. Il y aura une section par qualificatif de cette catégorie.
-- mois : oui pour avoir les liens vers les pages mensuelles et éphémérides (4 jours dans l'année)
-- alias : pour avoir des lien pour les alias en plus des qualificatif
function fun.checkDataCat( frame )
local category = trim(frame.args[1])
local monthLinks = frame .args.mois == 'oui'
local alias = frame.args.alias == 'oui'
local dataLink = mw.loadData( 'Module:Date/Data' )
local wikiList = {}
local currentYear = tonumber( os.date( '%Y' ) )
local columns = '<div style="-moz-column-width:5em;-webkit-column-width:5em;column-width:5em;-moz-column-gap:1em;-webkit-column-gap:1em;column-gap:1em;text-align:left;">'
local newSection
if monthLinks then
newSection = '\n\n== %s ==\n\n=== Années ===\n' .. columns
else
newSection ='\n\n== %s ==\n' .. columns
end
for field, dataField in pairs( dataLink ) do
-- boucle sur tous les qualificatif ayant pour catégorie le premier paramère
if dataField.cat == category or ( category == 'cat' and dataField.cat == field ) then
local monthInitialYear, initialYear
-- définition de l'année à partir de laquelle on va tester toutes les année / mois
if dataField.qualificatif == field or ( category == 'cat' and dataField.cat == field ) then
if dataField.annee and dataField.annee.aucun and dataField.annee.aucun < currentYear then
local aucun = ( dataField.annee.seul and dataField.annee.seul[1] ) or dataField.annee.aucun
initialYear = math.min( aucun - math.ceil( (currentYear - aucun) / 4 ), currentYear - 50 )
else
initialYear = currentYear - 50
end
if dataField.mois and tonumber( dataField.mois.aucun ) and ( tonumber( dataField.mois.aucun ) < currentYear ) then
local aucun = dataField.mois.aucun
monthInitialYear = math.min( aucun - math.ceil( (currentYear - aucun) / 4 ), currentYear - 8 )
else
monthInitialYear = currentYear - 8
end
elseif alias then
-- si le paramètre alias est défini on teste aussi tous les alias, sinon ils sont ignorés
initialYear = currentYear - 50
monthInitialYear = currentYear - 8
end
-- création de l'ensembles des liens
if initialYear then
-- ajout de lien vers les pages annuelles de l'année en court + 5 jusqu'à initialYear
table.insert( wikiList, string.format( newSection, field ) )
local fieldLink = ' ' .. field
if category == 'cat' then
fieldLink = ' ' .. dataField.qualificatif
end
for year = ( currentYear + 5 ), initialYear, -1 do
table.insert( wikiList, '\n* [[' .. year .. fieldLink ..'|' .. year .. ']]' )
end
table.insert( wikiList, '\n</div>' )
if monthLinks then
-- insertstion de liens vers les mois de l'année en court + 1 jusqu'à monthInitialYear
table.insert( wikiList, '\n\n=== Mois ===' )
local month, sep
for year = ( currentYear + 1 ), monthInitialYear, -1 do
table.insert( wikiList, '\n* ' .. year .. ' : ' )
sep = ' • '
for j = 1, 12 do
month = ucfirst( listeMois[j].nom ) .. ' '
if j == 12 then sep = ''
end
table.insert( wikiList, '[[' .. month .. year .. ' ' .. fieldLink .. '|' .. month .. ']]' .. sep )
end
end
-- insertion de quelques date pour tester les éphémérides
table.insert( wikiList, '\n\n=== Jours ===' )
table.insert( wikiList, '\n* [[1er janvier ' .. fieldLink .. ']]' )
table.insert( wikiList, '\n* [[14 mars ' .. fieldLink .. ']]' )
table.insert( wikiList, '\n* [[22 juin ' .. fieldLink .. ']]' )
table.insert( wikiList, '\n* [[3 septembre ' .. fieldLink .. ']]' )
end
end
end
end
return table.concat( wikiList )
end
--[[
Cette fonction retourne "CET" ou "CEST" selon que dans la pseudo-timezone en cours
c'est l'heure d'été ou l'heure d'hiver.
Cette fonction n'a de sens a priori que pour des modèles utilisés en Europe
Paramètre optionnel non nommé : "sans lien" : retourne le texte CET/CEST. sinon
retourne ce même texte avec un wikilien vers les articles correspondant
--]]
function fun.CEST(frame)
-- option : ne pas créer de wikilien
local opt = trim(frame.args[1] or frame:getParent().args[1])
-- on récupère l'information dans la zone courante
local t = mw.getContentLanguage():formatDate("I", nil, true)
if (t == "1") then -- heure d'été
if (opt == "sans lien") then
return "CEST"
elseif (opt == "décalage") then
return "2"
else
return "[[Heure d'été d'Europe centrale|CEST]]"
end
else -- heure d'hiver (ou autre zone où ça ne s'applique pas)
if (opt == "sans lien") then
return "CET"
elseif (opt == "décalage") then
return "1"
else
return "[[Heure normale d'Europe centrale|CET]]"
end
end
end
return fun