Aller au contenu

Module:Durée

Cette page fait l’objet d’une mesure de semi-protection étendue.
Une page de Wikipédia, l'encyclopédie libre.
Ceci est une version archivée de cette page, en date du 9 février 2024 à 09:35 et modifiée en dernier par Od1n (discuter | contributions) (support des leading/trailing spaces dans le paramètre "mois" ; pour complétion parce que c'est déjà supporté ailleurs, parce que tonumber() nettoie ces espaces (e.g. tonumber(' 42 ') est géré et donne bien 42)). Elle peut contenir des erreurs, des inexactitudes ou des contenus vandalisés non présents dans la version actuelle.

 Documentation[voir] [modifier] [historique] [purger]

Utilisation

Fonctions exportables :

  • duree(frame) – Fonction principale utilisable dans les modèles.
  • _duree(args) – Fonction pour utilisation dans d'autres modules avec le tableau des paramètres.

Autres fonctions :

  • joursMois(m, a)
  • erreur(texte)
  • determinationMois(mois)


local p = {}

local Outils = require 'Module:Outils'

-- liste des mois, écriture exacte et simplifiée, en minuscule
local liste_mois = {
	{ "janvier", "jan.", "janv.", "jan", "janv", "january", nJour = 31 },
	{ "février", "fevrier", "fev.", "fev", "fév.", "fév", "february", nJour = 28 },
	{ "mars", "mar.", "mar", "march", nJour = 31 },
	{ "avril", "avr.", "avr", "apr", "april", nJour = 30 },
	{ "mai", "may", nJour = 31 },
	{ "juin", "jun", "june", nJour = 30 },
	{ "juillet", "juil.", "juil", "juill.", "juill", "jul", "july", nJour = 31 },
	{ "août", "aout", "aou", "aug", "august", nJour = 31 },
	{ "septembre", "sept.", "sept", "sep.", "sep", "september", nJour = 30 },
	{ "octobre", "oct.", "oct", "october", nJour = 31 },
	{ "novembre", "nov.", "nov", "november", nJour = 30 },
	{ "décembre", "decembre", "déc.", "dec.", "dec", "déc", "december", nJour = 31 },
}

local function joursMois( m, a )
	a = a or 1
	if m == 0 then
		return 31
	elseif m == 2 then
		local b = ( a % 4 == 0 ) and ( ( a % 100 ~= 0 ) or ( a % 400 == 0 ) )
		return 28 + ( b and 1 or 0 )
	else
		return liste_mois[m].nJour
	end
end

local function erreur( texte )
	local cat = '[[Catégorie:Page utilisant un modèle avec une syntaxe erronée|Durée]]'
	local message = '<span class="error">erreur : '  .. texte .. '</span>'
	local ns = mw.title.getCurrentTitle().namespace
	if ns == 0 then
		return message .. cat
	else
		return message
	end
end

---
local function determinationMois( mois )
	if tonumber( mois ) then
		local num = math.floor( tonumber( mois ) )
		if num > 0 and num <= 12 then
			return num
		end
	elseif type( mois ) == 'string' then
		mois = mw.text.trim( mois )
		if mois ~= '' then
			local nom = mw.ustring.lower( mois )
			for num = 1, 12 do
				local i = 1
				while liste_mois[num][i] do
					if liste_mois[num][i] == nom then
						return num
					end
					i = i + 1
				end
			end
		end
	end
end

function p._duree( args )
	local maintenant = os.date( '!*t' )
	local fuseau = mw.getContentLanguage():formatDate("Z", nil, true)/3600
	if maintenant.hour + fuseau > 23 then
		maintenant.day = maintenant.day + 1
	end

	local enjours = args["en jours"]
	local enmois = args["en mois"]
	local enanneesetjours = args["en années et jours"]
	local enannee = not enanneesetjours and (args["en année"] or args["en années"])
	local raw = (args["raw"] and args["raw"] ~= "-") or (args["brut"] and args["brut"] ~= "-")

	local precision = 'jour'
	local jour1 = tonumber( args[1] )
	local mois1 = determinationMois( args[2] )
	local annee1 = tonumber( args[3] )
	if jour1 and jour1 > 31 and (not annee1 or annee1 <= 31) then
		local y = jour1
		jour1 = annee1
		annee1 = y
	end
	if not jour1 then
		precision = 'mois'
		-- jour1 = maintenant.day
		jour1 = 1
	end
	if not mois1 then
		if precision == 'mois' then
			precision = 'an'
			-- mois1 = maintenant.month
			mois1 = 1
		elseif not args.noerror then
			return erreur( 'mois invalide (' .. ( args[2] or '' ) .. ')' )
		else
			return
		end
	end
	if not annee1 then
		if precision == 'an' then
			return
			-- return erreur( 'aucune année fournit' ) -- suggestion
		else
			annee1 = maintenant.year
		end
	end

	local jour2 = tonumber( args[4] ) or maintenant.day
	local mois2 = determinationMois( args[5] ) or maintenant.month
	local annee2 = tonumber( args[6])  or maintenant.year
	if jour2 > 31 and annee2 <= 31 then
		local y = jour2
		jour2 = annee2
		annee2 = y
	end

	local tri = os.difftime(
		os.time{ year = annee2, month = mois2, day = jour2 },
		os.time{ year = annee1, month = mois1, day = jour1 }
		) / 86400
	if tri < 0 then
		if not args.noerror then
			return erreur( 'durée inférieure à 0' )
		else
			return
		end
	end
	local nbjours = tri
	tri = 0 .. tostring( tri )
	tri = string.rep( '&', 16 - #tri ) .. tri
	local textattrs = { class = 'datasortkey', ['data-sort-value'] = tri }

	if enjours then
		if raw then
			return nbjours
		else
			local moduleUnite = require 'Module:Unité'
			local unit
			if not args['masquer texte'] or args['masquer texte'] == '' then
				if nbjours> 1 then unit = 'jours' else unit = 'jour' end
			end
			nbjours = moduleUnite._unite({nbjours, unit})
			if args.sorttype == 'raw' then return nbjours else
				return mw.text.tag{ name = 'span', attrs = textattrs, content = nbjours }
			end
		end
	end

	local njour = jour2 - jour1
	local nmois = mois2 - mois1
	local nannee = annee2 - annee1
	if njour < 0 then
		nmois = nmois - 1
		njour = njour + joursMois( mois2 - 1, annee2 )
	end
	if nmois < 0 then
		nannee = nannee - 1
		nmois = nmois + 12
	end

	if enmois then
		local nbmois = nannee * 12 + nmois
		if raw then
			return nbmois
		else
			local moduleUnite = require 'Module:Unité'
			local unit
			if not args['masquer texte'] or args['masquer texte'] == '' then
				unit = 'mois'
			end
			nbmois = moduleUnite._unite({nbmois, unit})
			if args.sorttype == 'raw' then return nbmois else
				return mw.text.tag{ name = 'span', attrs = textattrs, content = nbmois }
			end
		end
	end
	if enannee then
		if raw then
			return nannee
		else
			local moduleUnite = require 'Module:Unité'
			local unit
			if not args['masquer texte'] or args['masquer texte'] == '' then
				if nannee > 1 then unit = 'ans' else unit = 'an' end
			end
			nannee = moduleUnite._unite({nannee, unit})
			if args.sorttype == 'raw' then return nannee else
				return mw.text.tag{ name = 'span', attrs = textattrs, content = nannee }
			end
		end
	end

	local result = {}
	local conjunction
	local function add( nombre, singulier, pluriel )
		if nombre > 0 then
			local texte = pluriel
			if nombre == 1 then
				texte = singulier
			end
			table.insert( result, nombre .. '\194\160' .. texte )
		end
	end
	if enanneesetjours then
		if args.conjtype == 'and' then conjunction = ' et ' else conjunction = ', ' end
		if precision ~= 'an' then
			nannee = annee2 - annee1
			njour = os.difftime(
				os.time{ year = annee2, month = mois2, day = jour2 },
				os.time{ year = annee2, month = mois1, day = jour1 }
				) / 86400
			if njour < 0 then
				nannee = nannee - 1
				njour = os.difftime(
					os.time{ year = annee2, month = mois2, day = jour2 },
					os.time{ year = annee2, month = 1, day = 1}
					) / 86400
					+ os.difftime(
					os.time{ year = annee1 + 1, month = 1, day = 1},
					os.time{ year = annee1, month = mois1, day = jour1 }
					) / 86400
			end
			add( nannee, 'an', 'ans' )
			add( njour, 'jour', 'jours' )
		else
			add( nannee, 'an', 'ans' )
		end
	else
		add( nannee, 'an', 'ans' )
		if precision ~= 'an' then
			add( nmois, 'mois', 'mois' )
		end
		if precision == 'jour' then
			add( njour, 'jour', 'jours' )
		end
	end

	if #result == 0 then
		result[1] = 'moins d’un ' .. precision
		tri = 0
	end

	local nanneescompl = mw.text.listToText( result, nil, conjunction )

	if args.sorttype == 'raw' then return nanneescompl else
		return mw.text.tag{ name = 'span', attrs = textattrs, content = nanneescompl }
	end
end


function p.duree( frame )
	local args = Outils.extractArgs( frame )
	for i = 1, 6 do
		if tonumber( args[i] ) == 0 then
			args[i] = ''
		end
	end

	return p._duree( args )
end

return p