FANDOM


-- Modulo per eseguire operazioni sulle date.
-- Copiato da https://it.wikipedia.org/wiki/Modulo:Data
 
require('Modulo:No globals')
 
local getArgs = require('Modulo:Arguments').getArgs
local errorCategory = '[[Categoria:Voci con errori del modulo Data]]'
-- classe esportata
local Date = {}
 
-------------------------------------------------------------------------------
--                    Funzioni di utilità
-------------------------------------------------------------------------------
 
-- Error handler per xpcall, formatta l'errore
local function errhandler(msg)
	local cat = mw.title.getCurrentTitle().namespace == 0 and errorCategory or ''
	return string.format('<span class="error">Errore: %s</span>%s', msg, cat)
end
 
local function isValidDate(date)
	return pcall(function() mw.getContentLanguage():formatDate('', date) end)
end
 
-- Controlla le date inserite dall'utente e le restituisce come oggetti Date
local function parseArgs(args, isCompare)
	local data1, data2, label1, label2
 
	if isCompare then
		data1, data2 = 'data1', 'data2'
		label1, label2 = 'prima data', 'seconda data'
	else
		data1, data2 = 'inizio', 'fine'
		label1, label2 = 'data di partenza', 'data di fine'
	end
 
	if not args[data1] then
		error(string.format('la %s è obbligatoria', label1), 2)
	elseif not isValidDate(args[data1]) then
		error(string.format('la %s non è valida', label1), 2)
	elseif not args[data2] then
		error(string.format('la %s è obbligatoria', label2), 2)
	elseif not isValidDate(args[data2]) then
		error(string.format('la %s non è valida', label2), 2)
	end
 
	return {
		d1 = Date:new(args[data1]),
		d2 = Date:new(args[data2])
	}
end
 
-------------------------------------------------------------------------------
--                               classe Date
-------------------------------------------------------------------------------
 
local function date_eq(t, t2)
	return t.ut == t2.ut
end
 
local function date_lt(t, t2)
	return t.ut < t2.ut
end
 
-- Costruisce un oggetto Date a partire da una stringa nel formato 
-- accettato dalla funzione parser #time.
function Date:new(str, precision)
	local self = {}
	setmetatable(self, { __index = Date, __eq = date_eq, __lt = date_lt })
	self.ut = tonumber(mw.getContentLanguage():formatDate('U', str, true))
	self.precision = precision or 11
	return self
end
 
-- Costruisce un oggetto Date a partire da una stringa nel formato:
-- "giorno mese_per_esteso anno" oppure "mese_per_esteso anno" oppure "anno".
function Date:newDMY(str)
	local months = {
		gennaio = 1, febbraio = 2, marzo = 3, aprile = 4, maggio = 5, giugno = 6,
		luglio = 7, agosto = 8, settembre = 9, ottobre = 10, novembre = 11, dicembre = 12
	}
	local success, result = pcall(function()
		local day, month, year = str:match("(%d+) (%a+) (%d+)")
		if day then
			return Date:new(string.format('%d-%d-%d', year, months[month], day))
		else
			month, year = str:match("(%a+) (%d+)")
			if month then
				return Date:new(string.format('%d-%d', year, months[month]), 10)
			else
				return Date:new(string.format('%d', str:match("(%d+)")), 9)
			end
		end
	end )
	return success and result or nil
end
 
-- Restituisce una stringa che rappresenta la data, senza l'ora.
function Date:getDateString()
	local fmt = self.precision == 9 and 'Y' or
				(self.precision == 10 and 'F Y' or
				(self.precision == 11 and 'j F Y' or 'j F Y'))
	return (mw.getContentLanguage():formatDate(fmt, '@' .. self.ut):gsub('^1%s', '1º '))
end
 
-- Restituisce un nuovo oggetto Date la cui data è avanzata del numero di giorni specificati.
function Date:addDays(days)
	return Date:new('@' .. (self.ut + days * 86400))
end
 
-- Funzione di utilità per Date:diffYMD e Date:diff
-- Aggiunge un eventuale prefisso e suffisso al risultato invece del segno.
-- L'ultimo parametro diffVal è utilizzato solo da diff per evitare che
-- {{#invoke:Data|diff|inizio=2016/01/01|fine=2015/12/31|magnitudine=anni}} ritorni "-0 anni".
local function formatResult(result, date1, date2, dir, diffVal)
	local ret
	if dir then
		-- ritorna il 'fa' anche con date1.ut == date2.ut (si potrebbe configurare con un parametro)
		ret = date1.ut < date2.ut and 'tra ' .. result or result .. ' fa'
	else
		ret = (date1.ut <= date2.ut or diffVal == 0) and result or '-' .. result
	end
	return ret
end
 
-- Restituisce la differenza con la data date2 in anni, mesi e giorni.
function Date:diffYMD(date2, rawTable, dir)
	local monthdays = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
	local d1, d2 = os.date('*t', self.ut), os.date('*t', date2.ut)
	local ret = { seconds = math.abs(self.ut - date2.ut) }
 
	if self.ut >= date2.ut then d1, d2 = d2, d1 end  
 
	-- anni
	ret.years = d2.year - d1.year
	if ret.years > 0 and (d1.month > d2.month or (d1.month == d2.month and d1.day > d2.day)) then
		ret.years = ret.years - 1
	end
	-- mesi
	ret.months = (d2.month - d1.month + 12) % 12
	if d1.day > d2.day then
		ret.months = (ret.months == 0 and d1.year < d2.year) and 11 or ret.months - 1
	end
	-- giorni
	ret.days = d2.day >= d1.day and d2.day - d1.day or (monthdays[d1.month] - d1.day) + d2.day
 
	-- utilizza la sequence per ritornare anche la versione testuale 
	if ret.years > 0 then
		table.insert(ret, string.format('%s %s', ret.years, ret.years == 1 and 'anno' or 'anni'))
	end
	if ret.months > 0 then
		table.insert(ret, string.format('%s %s', ret.months, ret.months == 1 and 'mese' or 'mesi'))
	end
	if ret.days > 0 or ret.years + ret.months + ret.days == 0 then
		table.insert(ret, string.format('%s %s', ret.days, ret.days == 1 and 'giorno' or 'giorni'))
	end
 
	return rawTable and ret or formatResult(mw.text.listToText(ret, ',&#32;', '&#32;e&#32;'), self, date2, dir)
end
 
-- Funzione di utilità per Date:diff
local function getMagnitudine(diff, magnitudine_min)
	local units = { 
	   secondi = 0, minuti = 1, ore = 2, giorni = 3, settimane = 4, mesi = 5, anni = 6
	}
	local ret
 
	if diff.seconds < 120 then -- minore di due minuti
		ret = 'secondi'
	elseif diff.seconds < 7200 then -- minore di due ore
		ret = 'minuti'
	elseif diff.seconds < 172800 then -- minore di due giorni
		ret = 'ore'
	elseif diff.years == 0 and diff.months < 2 then -- minore di due mesi
		ret = 'giorni'
	elseif diff.years < 2 then -- minore di due anni
		ret = 'mesi'
	else
		ret = 'anni'
	end
	-- utilizzo di magnitudine_min (il valore minimo quando è automatica)
	if magnitudine_min and units[magnitudine_min] then
		ret = units[magnitudine_min] > units[ret] and magnitudine_min or ret
	end
 
	return ret
end
 
-- Funzione di utilità per Date:diff
local function convert(seconds, unit, text, text2)
	local ret = math.floor(seconds / unit)
	return ret, string.format('%s %s', ret, ret == 1 and text or text2)
end
 
-- Restituisce la differenza con la data d2 in solo una tra le unità:
-- anni, mesi, settimane, giorni, ore, minuti e secondi.
function Date:diff(date2, magnitudine, magnitudine_min, dir)
	local diff, ret, val, result
 
	diff = self:diffYMD(date2, true)
	magnitudine = magnitudine or getMagnitudine(diff, magnitudine_min)
 
	if magnitudine == 'secondi' then
		val, result = convert(diff.seconds, 1, 'secondo', 'secondi')
	elseif magnitudine == 'minuti' then
		val, result = convert(diff.seconds, 60, 'minuto', 'minuti')
	elseif magnitudine == 'ore' then
		val, result = convert(diff.seconds, 3600, 'ora', 'ore')
	elseif magnitudine == 'giorni' then
		val, result = convert(diff.seconds, 86400, 'giorno', 'giorni')
	elseif magnitudine == 'settimane' then
		val, result = convert(diff.seconds, 604800, 'settimana', 'settimane')
	elseif magnitudine == 'mesi' then
		val = diff.years * 12 + diff.months
		result = string.format('%s %s', val, val == 1 and 'mese' or 'mesi')
	else
		val = diff.years
		result = string.format('%s %s', diff.years, diff.years == 1 and 'anno' or 'anni')
	end
 
	return formatResult(result, self, date2, dir, val)
end
 
-------------------------------------------------------------------------------
--                                    API
-------------------------------------------------------------------------------
 
local p = { Date = Date }
 
-- Entry point per {{#invoke:Data|diff}}
function p.diff(frame)
	local args = getArgs(frame)
	local success, result = xpcall(function() return parseArgs(args) end, errhandler)
	return success and result.d1:diff(result.d2, args.magnitudine, args['magnitudine min'], args.dir) or result
end
 
-- Entry point per {{#invoke:Data|diff_ymd}}
function p.diff_ymd(frame)
	local args = getArgs(frame)
	local success, result = xpcall(function() return parseArgs(args) end, errhandler)
	return success and result.d1:diffYMD(result.d2, false, args.dir) or result
end
 
-- Entry point per {{#invoke:Data|compare}}
function p.compare(frame)
	local success, result = xpcall(function() return parseArgs(getArgs(frame), true) end, errhandler)
	return success and (result.d1 == result.d2 and 0 or ( result.d1 < result.d2 and -1 or 1 )) or result
end
 
return p
 
-- [[Categoria:Moduli Lua]]

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Inoltre su FANDOM

Wiki casuale