Modulo che implementa il template {{Fuso orario}}.

Ha una sottopagina di configurazione: Modulo:Fuso orario/Configurazione.


--[[
* Modulo che implementa il template Fuso orario.
]]--

require('strict')

local getArgs = require('Modulo:Arguments').getArgs
local mWikidata = require('Modulo:Wikidata')

-- Configurazione
local cfg = mw.loadData('Modulo:Fuso orario/Configurazione')

local p = {}

local function titleExists(name)
	local title = mw.title.new(name)
	return title and title.exists
end

local function makeSequence(tbl)
	local ret = {}
	for item, _ in pairs(tbl) do
		table.insert(ret, item)
	end
	return ret
end

local function compValues(val1, val2)
	val1 = val1:match('UTC(.*)%]%]'):gsub(':', '.')
	val2 = val2:match('UTC(.*)%]%]'):gsub(':', '.')
	return tonumber(val1) < tonumber(val2)
end

local function formatList(values)
	table.sort(values, compValues)
	return string.format('<ul><li>%s</li></ul>', mw.text.listToText(values, '</li><li>', '</li><li>'))
end

local function formatTimezones(items)
	local formattedItems = {}
	for _, item in ipairs(items) do
		table.insert(formattedItems, string.format('[[%s]]', mw.wikibase.getSitelink(item)))
	end
	return #formattedItems > 1 and formatList(formattedItems) or formattedItems[1]
end

-- per retrocompatibilità con l'input di Divisione amministrativa
local function formatUserInput(value)
	return titleExists('UTC' .. value) and string.format('[[UTC%s]]', value) or nil
end

local function checkTimezone(item)
	local ret = cfg.validTimezones[item] and item or nil
	
	-- se non è tra i validTimezones verifica la proprietà "considerato essere uguale a (P460)"
	if not ret then
		ret = mWikidata._getProperty( { 'P460', from = item, formatting = 'raw', n = 1 } )
		if ret then
			ret = cfg.alias[ret] or ret
			ret = cfg.validTimezones[ret] and ret or nil
		end
	end
	
	-- invece di P460 in alcuni casi è stato usato P421
	if not ret then
		ret = mWikidata._getProperty( { 'P421', from = item, formatting = 'raw', n = 1 } )
		if ret then
			ret = cfg.alias[ret] or ret
			ret = cfg.validTimezones[ret] and ret or nil
		end
	end

	return ret
end

-- Se i claims hanno un qualifier P518 (parte coinvolta), restituisce quelli
-- il cui valore è tra i P131 dell'elemento, altrimenti quelli senza P518.
local function filterByP518(claims, args)
	local inP518, noP518 = {}, {}
	for _, claim in ipairs(claims) do
		local items = mWikidata._formatQualifiers(claim, 'P518', { formatting = 'raw' }, true)
		if #items > 0 then
			for _, item in ipairs(items) do
				if mWikidata._indexOf({ 'P131', item, from = args.from }) then
					table.insert(inP518, claim)
				end
			end
		else
			table.insert(noP518, claim)
		end
	end
	return #inP518 > 0 and inP518 or noP518
end

local function getTimezones(args)
	local ret = {}
	local country = mWikidata._getProperty( { 'P17', from = args.from, formatting = 'raw', n = 1 } )
	-- entità amministrative soppresse con P17 a novalue (in futuro il modulo:Wikidata restituirà nil)
	if country == "''nessun valore''" then
		country = nil
	end

	-- ricerca la proprietà fuso orario (P421) 
	local claims = mWikidata._getClaims('P421', { from = args.from } ) or {}
	-- risultato temporaneo per Q142
	if #claims == 0 and (args.iso3166 == 'FRA'  or country == 'Q142') then
		return { 'Q6655' }
	end
	-- se non presente la ricerca nell'elemento ottenuto da iso3166
	if #claims == 0 and args.iso3166 then
		claims = mWikidata._getClaims('P421', { noqualifier = 'P518', from = cfg.iso3166[args.iso3166] } ) or {}
	end
	-- se non presente la ricerca nell'item in paese (P17)
	if #claims == 0 then
		claims = mWikidata._getClaims('P421', { noqualifier = 'P518', from = country } ) or {}
	end
	-- se non è uno Stato filtra i fusi orari in base a P518 (parte coinvolta), se presente
	if not mWikidata._instanceOf({ 'Q6256', from = args.from }) then
		-- per ora limitato alla Spagna, per una introduzione graduale
		if country == 'Q29' then
			claims = filterByP518(claims, args)
		end
	end

	for _, claim in ipairs(claims) do
		local item = mWikidata._formatStatement(claim, { formatting = 'raw' })
		-- se ha "periodo di validità (P1264)" deve valere "tempo standard (Q1777301)"
		local period = mWikidata._formatQualifiers(claim, 'P1264', { formatting = 'raw' })
		if not period or period == 'Q1777301' then
			item = cfg.alias[item] or item
			item = checkTimezone(item)
			if item then
				-- chiave = boolean, per non avere duplicati
				ret[item] = true
			end
		end
	end

	-- trasforma in una più semplice sequence
	return makeSequence(ret)
end

local function getWikidataCategory(userval, wdval)
	local cat
	if userval then
		if not wdval then
			cat = 'P421 assente su Wikidata'
		elseif wdval == userval then
			cat = 'P421 uguale su Wikidata'
		else
			cat = 'P421 differente su Wikidata'
		end
	elseif wdval then
		cat = 'P421 letta da Wikidata'
	end
	return string.format('[[Categoria:%s]]', cat)
end

-- Per l'utilizzo da altro modulo
function p._main(args)
	local userval, wdval, cat

	-- valore utente
	if args[1] then
		userval = formatUserInput(args[1])
		if not userval and args.errmsg then
			local msg = mw.ustring.gsub(args.errmsg, '\\{', '{')
			msg = mw.ustring.gsub(msg, '\\}', '}')
			return mw.getCurrentFrame():preprocess(msg)
		end
	end

	-- valore letto da Wikidata
	local timezones = getTimezones(args)
	if #timezones == 1 or (#timezones > 1 and args.multiplo ~= 'no') then
		wdval = formatTimezones(timezones)
	end

	-- categorie di servizio
	if mw.title.getCurrentTitle().namespace == 0 then
		if not userval and not wdval and args.cat then
			cat = string.format('[[Categoria:%s]]', args.cat)
		elseif userval or (wdval and #timezones <= 1) then
			cat = getWikidataCategory(userval, wdval)
		end
	end

	return (userval or wdval or '') .. (cat or '')
end

-- Entry-point per il template {{Fuso orario}}
function p.main(frame)
	return p._main(getArgs(frame, {parentOnly = true}))
end

return p