Modulo:Date
La documentazione per questo modulo può essere creata in Modulo:Date/man
--modulo contenente funzioni per la gestione delle date
local p = {}
local c = require('Modulo:Common')
--dal value, crea un oggetto date che rappresenta la data, da usare per le successive manipolazioni
function p.getDate(value)
if value and value.time then
date = {century, decade, year, month, day, ac = false, precision, calendar}
--esempio di data: +1862-08-29T00:00:00Z
date.year, date.month, date.day = value.time:match( '.+(%d?%d%d%d%d)%-(%d%d)%-(%d%d).+' )
if date.year and date.month and date.day then
date.year = tonumber(date.year)
date.century = math.ceil(date.year / 100)
date.decade = (date.year % 100) - ((date.year % 100) % 10)
date.ac = (value.time:sub(1, 1) == '-')
date.precision = value.precision
date.calendar = p.getCalendar(value)
return date
else
mw.log('Formato data non riconosciuto!')
end
end
end
--fornisce una lista di oggetti date presi dalla property fornita (di default, con ordinamento ASC)
function p.getDatesFromProperty(property, order)
local list = {}
claims = c.sortClaimsByDate(c.getClaimsByProperty(property) or {}, order)
for index, claim in pairs(claims) do
date = p.getDate(c.getClaimValue(claim))
if date then table.insert(list, date) end
end
return list
end
--ritorna la lista di tutte le date per la proprietà indicata, concatenate da "-" o da "tra il e il"
function p.getAllDates(property)
local list = {} --lista di tutte le date
claims = c.getClaimsByProperty(property) or {}
for index, claim in pairs(claims) do
local val = p.getDate(c.getClaimValue(claim))
local preStringa = ''
local circa = c.getLabelFromValue(c.getQualifierValueFromClaim(claim, 'P1480'));
circa = (circa and circa..' ') or ''
local ante = p.getDate(c.getQualifierValueFromClaim(claim, 'P1326'))
local post = p.getDate(c.getQualifierValueFromClaim(claim, 'P1319'))
if val then
preStringa = circa .. p.formatDate(val) .. ', '
end
if ante and post then
--caso "tra il": ritorniamo direttamente questa coppia di date con la stringa "tra il"
return preStringa .. 'tra il ' .. p.formatDate(post) .. ' e il ' .. p.formatDate(ante)
elseif ante ~=nil and post == nil then
--caso ante
table.insert(list, preStringa .. 'prima del ' .. p.formatDate(ante))
elseif ante ==nil and post ~= nil then
--caso post
table.insert(list, preStringa .. 'dopo il ' .. p.formatDate(post))
elseif val then
--caso normale
table.insert(list, circa .. p.formatDate(val))
end
end
--a questo punto va costruita la stringa finale
return c.concat(list, '-')
end
--trova la "data comune" più accurata possibile tra la lista di date fornita
function p.getCommonDate(dates)
commonDate = {}
for k, v in pairs(dates[1] or {}) do commonDate[k] = v end --deep copy
for i, date in pairs(dates or {}) do
for k, v in pairs(date) do
if v ~= commonDate[k] then commonDate[k] = nil end
end
if date[precision] and commonDate.precision and date[precision] < commonDate.precision then
commonDate.precision = date[precision]
end
end
return commonDate
end
function p.getAnteOrPostFromProperty(property)
claims = c.getClaimsByProperty(property) or {}
for index, claim in pairs(claims) do
ante = p.getDate(c.getQualifierValueFromClaim(claim, 'P1326'))
post = p.getDate(c.getQualifierValueFromClaim(claim, 'P1319'))
if ante then
return ante
elseif post then
return post
end
end
end
function p.addYears(date, years)
local ac = date.ac
date.year = date.year * (date.ac and -1 or 1) + years
date.ac = not(date.year > 0)
date.year = math.abs(date.year)
if date.year == 0 then date.ac = not(ac) end
if ac ~= date.ac then
date.year = date.year + 1 --year 0 does not exist!
end
date.century = math.ceil(date.year / 100)
return date
end
--ritorna la data formattata a seconda della precisione
function p.formatDate(date)
if date and date.precision then
--precision: 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day
if date.precision == 7 then
return p.formatCentury(date)
elseif date.precision == 8 then
return p.formatDecadeCentury(date)
elseif date.precision == 9 then
return p.formatYear(date)
elseif date.precision == 10 then
return p.formatMonth(date) .. ' ' .. p.formatYear(date)
elseif date.precision == 11 then
return p.formatDayMonth(date) .. ' ' .. p.formatYear(date)
end
end
end
--il nome secolo nel formato "XII secolo"
function p.formatCentury(date)
if date and date.century then return c.toRoman(date.century) ..' secolo' .. p.avantiCristo(date) end
end
--il nome del decennio nel formato "anni 50"
function p.formatDecade(date)
if date and date.decade then return 'anni ' .. date.decade end
end
--il nome del decennio nel formato "anni 50 del II secolo a.C."
function p.formatDecadeCentury(date)
if date and date.decade and date.century then return p.formatDecade(date) .. ' del ' .. p.formatCentury(date) end
end
--ritorna l'anno formattato con a.C. se necessario
function p.formatYear(date)
if date and date.year then return date.year .. p.avantiCristo(date) end
end
--ritorna il mese in formato esteso (gennaio, febbraio...)
function p.formatMonth(date)
day = 1 --per dare un giorno "vero" al formatDate (con 0 potrebbe ritornare risultati imprevisti)
if date and date.year and date.month then
return mw.getLanguage('it'):formatDate('F', date.year..'-'..date.month..'-'..day)
end
end
--ritorna giorno+mese in formato esteso (1° gennaio, 12 febbraio...)
function p.formatDayMonth(date)
if date and date.year and date.month and date.day then
return mw.getLanguage('it'):formatDate('j F', date.year..'-'..date.month..'-'..date.day):gsub('^1%s', '1° ')
end
end
function p.avantiCristo(date)
return (date and date.ac and ' a.C.') or ''
end
--ritorna il nome del calendario in testo puro
function p.getCalendar(value)
calendarmodel = ''
--TODO capire perché diavolo a volte arriva come string e come sistemare
if type(value) == 'string' then
calendarmodel = value
elseif value and value.calendarmodel then
calendarmodel = value.calendarmodel
end
if calendarmodel == 'http://www.wikidata.org/entity/Q1985786' then
return 'giuliano'
elseif calendarmodel == 'http://www.wikidata.org/entity/Q1985727' then
return 'gregoriano'
else
mw.log('Calendario non riconosciuto: ' .. calendarmodel)
return ''
end
end
--ritorna una stringa con il tipo di calendario e il link
function p.linkCalendar(calendar)
if p.getCalendar(calendar) == 'giuliano' then
return '\'\'[[:w:Calendario giuliano|giul.]]\'\''
elseif p.getCalendar(calendar) == 'gregoriano' then
return '\'\'[[:w:Calendario gregoriano|greg.]]\'\''
else
return ''
end
end
function p.monthToNumber(month)
if month == 'gennaio' then return '01'
elseif month == 'febbraio' then return '02'
elseif month == 'marzo' then return '03'
elseif month == 'aprile' then return '04'
elseif month == 'maggio' then return '05'
elseif month == 'giugno' then return '06'
elseif month == 'luglio' then return '07'
elseif month == 'agosto' then return '08'
elseif month == 'settembre' then return '09'
elseif month == 'ottobre' then return '10'
elseif month == 'novembre' then return '11'
elseif month == 'dicembre' then return '12'
end
end
function p.numberToMonth(mon)
if mon == '01' then return 'gennaio'
elseif mon == '02' then return 'febbraio'
elseif mon == '03' then return 'marzo'
elseif mon == '04' then return 'aprile'
elseif mon == '05' then return 'maggio'
elseif mon == '06' then return 'giugno'
elseif mon == '07' then return 'luglio'
elseif mon == '08' then return 'agosto'
elseif mon == '09' then return 'settembre'
elseif mon == '10' then return 'ottobre'
elseif mon == '11' then return 'novembre'
elseif mon == '12' then return 'dicembre'
end
end
--prende una data in formato "1° febbraio" e ritorna "02-01"
function p.getNumericDate(frame)
stringDate = frame.args[1]:gsub("°", "")
day, month = stringDate:match("(%w+) (%w+)")
day = string.format("%02d", day)
return p.monthToNumber(month)..'-'..day
end
--prende una data nel formato 2018.01 (archivio del bar) e ritorna "2018"
function p.getBarYear(frame)
stringDate = frame.args[1]
year, mon = stringDate:match("(%w+).(%w+)")
return year
end
--prende una data nel formato 2018.01 (archivio del bar) e ritorna "gennaio"
function p.getBarMonth(frame)
stringDate = frame.args[1]
year, mon = stringDate:match("(%w+).(%w+)")
return p.numberToMonth(mon)
end
-- prende una data e ritorna il secolo
function p.secolo(frame)
stringDate = frame.args[1]
if stringDate:lower():match("secolo") then
stringDate = stringDate:gsub("Secolo", "secolo"):gsub("a.c.", "a.C.")
return stringDate
else
stringDate = stringDate:lower():gsub("[-/].*", "")
str = " secolo"
if stringDate:match("a.c.") then
stringDate = stringDate:gsub(" a.c.", "")
str = str .. " a.C."
end
return c.toRoman(math.ceil(stringDate / 100)) .. str
end
end
function p.absoluteDate(stringDate)
if not stringDate then
return nil
end
if stringDate:match("a.C.") then
stringDate = stringDate:gsub(" a.C.", "")
numDate = tonumber(stringDate)
if numDate then
return -numDate
else
return nil
end
else
return tonumber(stringDate)
end
end
function p.dayBefore(frame)
local day = frame.args[1]
local month = p.monthToNumber(frame.args[2])
mw.log('day: '..day)
mw.log('month: '..month)
local endtime = os.time({day = day - 1, month = month, year = os.date("%Y")})
return os.date("%d", endtime):match("0*(%d+)") .. ' ' .. p.numberToMonth(os.date("%m", endtime))
end
function p.dayAfter(frame)
local day = frame.args[1]
local month = p.monthToNumber(frame.args[2])
local endtime = os.time({day = day + 1, month = month, year = os.date("%Y")})
return os.date("%d", endtime):match("0*(%d+)") .. ' ' .. p.numberToMonth(os.date("%m", endtime))
end
return p