Modulo:Data/sandbox
--[[
* Modulo per eseguire operazioni sulle date.
* Utilizzato da template come {{Età wikipediana}} e {{Tempo trascorso}}.
]]
require('strict')
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, ', ', ' e '), 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
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.