Modulo per eseguire operazioni sulle date.

Funzioni

diff

Questa funzione ritorna la differenza tra le date inserite tramite i parametri "inizio" e "fine" in una sola unità tra "anni", "mesi", "settimane", "giorni", "ore", "minuti" e "secondi". L'unità può essere specificata tramite il parametro "magnitudine", se non inserito viene utilizzata automaticamente l'unità più adatta. Il formato per le date è quello accettato dalla funzione parser #time.

Uso
  • {{#invoke:Data|diff|inizio=data1|fine=data2}}
Parametri
inizio: data di partenza
fine: data di arrivo, può essere successiva o anteriore a inizio, se anteriore verrà anteposto il segno "-" (meno) al risultato.
magnitudine: l'unità da ritornare nel risultato, tra "anni", "mesi", "settimane", "giorni", "ore", "minuti" e "secondi". Se non inserita è utilizzata automaticamente la più adatta.
magnitudine min: quando non è utilizzata magnitudine e il modulo utilizza automaticamente l'unità più adatta, serve per configurare l'unità minima da usare. Se per esempio "magnitudine min" viene impostata a "mesi" allora non verranno usate le unità minori (giorni, minuti e secondi) anche se queste fossero le più adatte. È utile quando il modulo è usato in un template: pur non conoscendo a priori le date che verranno utilizzate si può così stabilire una unità minima che verrà visualizzata.
dir: se impostato a qualunque valore, esempio "dir=sì", nel risultato invece del segno verrà utilizzato il prefisso "tra" se positivo (esempio: "tra 1 mese") o verrà appeso "fa" se negativo (esempio "un mese fa").
Esempi
  • {{#invoke:Data|diff|inizio=2016/01/01|fine=2016/02/10}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|diff|inizio=2016/01/01|fine=2016/02/10|magnitudine=mesi}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|diff|inizio=2016/01/01|fine=2014/07/01}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|diff|inizio=2016/01/01|fine=2014/07/01|magnitudine=anni}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.

Gli stessi esempi con dir=sì:

  • {{#invoke:Data|diff|inizio=2016/01/01|fine=2016/02/10|dir=sì}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|diff|inizio=2016/01/01|fine=2016/02/10|magnitudine=mesi|dir=sì}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|diff|inizio=2016/01/01|fine=2014/07/01|dir=sì}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|diff|inizio=2016/01/01|fine=2014/07/01|magnitudine=anni|dir=sì}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.

diff_ymd

Questa funzione ritorna la differenza in anni, mesi e giorni tra le date inserite tramite i parametri "inizio" e "fine". Il formato per le date è quello accettato dalla funzione parser #time.

Uso
  • {{#invoke:Data|diff_ymd|inizio=data1|fine=data2}}
Parametri
inizio: data di partenza
fine: data di arrivo, può essere successiva o anteriore a inizio, se anteriore verrà anteposto il segno "-" (meno) al risultato.
dir: se impostato a qualunque valore, esempio "dir=sì", nel risultato invece del segno verrà utilizzato il prefisso "tra" se positivo (esempio: "tra 1 mese e 1 giorno") o verrà appeso "fa" se negativo (esempio "un mese e un giorno fa").
Esempi
  • {{#invoke:Data|diff_ymd|inizio=2016/01/01|fine=2015/01/01}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|diff_ymd|inizio=2016/01/01|fine=2017/03/04}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|diff_ymd|inizio=2016/01/01|fine=2012/12/31}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.

Gli stessi esempi con dir=sì:

  • {{#invoke:Data|diff_ymd|inizio=2016/01/01|fine=2015/01/01|dir=sì}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|diff_ymd|inizio=2016/01/01|fine=2017/03/04|dir=sì}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|diff_ymd|inizio=2016/01/01|fine=2012/12/31|dir=sì}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.

compare

Questa funzione confronta due date e restituisce 0 se le date sono uguali, -1 se la prima è anteriore alla seconda, altrimenti 1. Il formato per le date è quello accettato dalla funzione parser #time.

Uso
  • {{#invoke:Data|compare|data1=prima data|data2=seconda data}}
Parametri
data1: la prima data
data2: la seconda data
Esempi
  • {{#invoke:Data|compare|data1=2016/01/01|data2=2016/01/01}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|compare|data1=2016/01/01|data2=2016/01/10}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.
  • {{#invoke:Data|compare|data1=2016/01/10|data2=2016/01/01}}Errore Lua in package.lua alla linea 80: module 'Modulo:No globals' not found.

Utilizzo da un altro modulo

Oltre che attraverso #invoke, il modulo può essere utilizzato tramite "require" da un altro modulo. Le stesse funzioni sono disponibili tramite la classe Date:

local Date = require('Modulo:Data').Date
Esempio
local Date = require('Modulo:Data').Date
local p = {}

function p.main(frame)
	local inizio, fine, diff1, diff2, text1, text2, anteriore

	inizio = Date:new('2016/01/01')
	fine = Date:new('2017/03/04')

	-- utilizzo della funzione diff
	diff1 = inizio:diff(fine, 'mesi')

	-- utilizzo della funzione diff_ymd
	diff2 = inizio:diffYMD(fine)

	-- data per esteso
	text1 = inizio:getDateString()
	text2 = fine:getDateString()

	-- confronto
	anteriore = inizio < fine
	
	return string.format('La differenza tra il %s e il %s è di %s, più precisamente di %s. ' ..
						 'La prima data è anteriore alla seconda: %s.',
						 text1, text2, diff1, diff2, tostring(anteriore))
end

return p

Unit test

Unit test per questo modulo sono disponibili a Modulo:Data/test, per la loro esecuzione visitare Discussioni_modulo:Data/test.


--[[
* Modulo per eseguire operazioni sulle date.
* Utilizzato da template come {{Età wikipediana}} e {{Tempo trascorso}}.
]]

local getArgs = require('Modulo:Arguments').getArgs
require('Modulo:No globals')

-------------------------------------------------------------------------------
--                    Funzioni di utilità
-------------------------------------------------------------------------------

local function isValidDate(date)
	return pcall(function() mw.getContentLanguage():formatDate('', date) end)
end

-- Controlla args.from e args.to e li ritorna in Unix time
local function parseArgs(args)
	if not args.to then
		error('la data di arrivo è obbligatoria')
	elseif not isValidDate(args.to) then
		error('la data di arrivo non è valida')
	elseif args.from and not isValidDate(args.from) then
		error('la data di partenza non è valida')
	end

	return { 
		d1 = mw.getContentLanguage():formatDate('U', args.to),
		d2 = args.from and mw.getContentLanguage():formatDate('U', args.from) or os.time()
	}
end

-- Error handler per xpcall, formatta l'errore
local function errhandler(msg)
	return string.format('<span class="error">Errore: %s</span>', msg:match('.+%d:%s(.+)$'))
end

-------------------------------------------------------------------------------
--                               dateDiffYMS
-------------------------------------------------------------------------------

-- Ritorna la differenza in anni, mesi e giorni tra le date d1 e d2 (Unix time).
-- Se rawTable è true ritorna una table con le chiavi: year, month, day, seconds e dir.
local function dateDiffYMS(d1, d2, rawTable)
	local monthdays = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
	local ret = { dir = 1, seconds = math.abs(d1 - d2) }

	d1, d2 = os.date('*t', d1), os.date('*t', d2)

	-- se d1 >= d2 inverte
	if d1.year > d2.year or
	   (d1.year == d2.year and d1.month > d2.month) or
	   (d1.year == d2.year and d1.month == d2.month and d1.day >= d2.day) then
		d1, d2 = d2, d1
		ret.dir = -1
	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 mw.text.listToText(ret, ',&#32;', '&#32;e&#32;')
end

-------------------------------------------------------------------------------
--                               dateDiff
-------------------------------------------------------------------------------

-- Funzione di utilità per dateDiff
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 dateDiff
local function convert(seconds, unit, text, text2)
	local ret = math.floor(seconds / unit)
	return string.format('%s %s', ret, ret == 1 and text or text2)
end

-- Ritorna la differenza tra le date d1 e d2 (Unix time) in solo una tra le unità:
-- anni, mesi, settimane, giorni, ore, minuti e secondi.
local function dateDiff(d1, d2, magnitudine, magnitudine_min)
	local diff, ret, dir, val

	diff = dateDiffYMS(d1, d2, true)
	magnitudine = magnitudine or getMagnitudine(diff, magnitudine_min)

	if magnitudine == 'secondi' then
		ret = convert(diff.seconds, 1, 'secondo', 'secondi')
	elseif magnitudine == 'minuti' then
		ret = convert(diff.seconds, 60, 'minuto', 'minuti')
	elseif magnitudine == 'ore' then
		ret = convert(diff.seconds, 3600, 'ora', 'ore')
	elseif magnitudine == 'giorni' then
		ret = convert(diff.seconds, 86400, 'giorno', 'giorni')
	elseif magnitudine == 'settimane' then
		ret = convert(diff.seconds, 604800, 'settimana', 'settimane')
	elseif magnitudine == 'mesi' then
		val = diff.years * 12 + diff.months
		ret = string.format('%s %s', val, val == 1 and 'mese' or 'mesi')
	else
		ret = string.format('%s %s', diff.years, diff.years == 1 and 'anno' or 'anni')
	end
 
	return d1 > d2 and 'tra ' .. ret or ret .. ' fa'
end

-------------------------------------------------------------------------------
--                                    API
-------------------------------------------------------------------------------

local p = {}

-- Per utilizzare diff da un altro modulo.
function p._diff(args)
	local success, result = xpcall(function() return parseArgs(args) end, errhandler)
	return success and dateDiff(result.d1, result.d2, args.magnitudine, args['magnitudine min']) or result
end

-- Per utilizzare diff_yms da un altro modulo.
function p._diff_yms(args)
	local success, result = xpcall(function() return parseArgs(args) end, errhandler)
	return success and dateDiffYMS(result.d1, result.d2) or result
end

-- Entry point per {{#invoke:Data|diff}}
function p.diff(frame)
	return p._diff(getArgs(frame))
end

-- Entry point per {{#invoke:Data|diff_yms}}
function p.diff_yms(frame)
	return p._diff_yms(getArgs(frame))
end

return p