Module:Durée

De USAC-CGT
Révision datée du 6 août 2023 à 22:45 par wikipedia>Golmote (args.noerror pour désactiver les erreurs)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigation Aller à la recherche

La documentation pour ce module peut être créée à Module:Durée/doc

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' and mw.text.trim( 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

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