Módulo:Data/Testes
DescriçãoEste módulo tem funções auxiliares para criar infocaixas onde se mostra uma ligação para artigos sobre eventos com datas. Ver módulo de dados Módulo:Data/Dados UsoFunções que podem ser usadas de uma predefinição
Funções que podem ser usadas de outro módulo
Módulos externos que este módulo precisa para funcionar
modeloData( frame )Parâmetros
local fun = {}
local Ferramentas = require 'Módulo:Ferramentas'
-- carregando o banco de dados listando algumas páginas existentes para evitar "ifexist".
local dataLinks
local success, resultado = pcall ( mw.loadData, 'Módulo:Data/Dados' )
if success then
dataLinks = resultado
else
-- proteção no caso ou sub módulos serem mal modificados
dataLinks = { [''] = { mes = { vazio = 1000, todos = { 1773, 2014 } }, } }
end
-- limpa um parâmetro sem nome (vira os espaços no começo e no fim)
-- voltar nil se o texto estiver vazio ou não estiver enviando mensagens de texto. A atenção é importante para a função que a utiliza.
local trim = Ferramentas.trim
-- Função destinada a meter a primeira letra do mês em minúscula do mês :
-- uso de string porque nenhum mês começa com uma letra não ascii em português ou inglês.
local function lcfirst( str )
return str:sub( 1, 1 ):lower() .. str:sub( 2 )
end
-- lista de meses, escritas exatamente com alias, em minúscula
local listaMes = {
{ num = 1, nDia = 31, abrev = 'jan.', nome = 'janeiro', alias = { 'jan.', 'jan.', 'jan', 'janeiro', 'january'} },
{ num = 2, nDia = 29, abrev = 'fev.', nome = 'fevereiro', alias = { 'fevereiro', 'fev.', 'fev', 'february'} },
{ num = 3, nDia = 31, abrev = 'mar.', nome = 'março', alias = { 'mar.', 'mar', 'março', 'march' } },
{ num = 4, nDia = 30, abrev = 'abr.', nome = 'abril', alias = { 'abr.', 'abr','abril', 'april' } },
{ num = 5, nDia = 31, abrev = 'maio', nome = 'maio', alias = { 'maio', 'may' } },
{ num = 6, nDia = 30, abrev = 'jun.', nome = 'junho', alias = { 'jun', 'june' } },
{ num = 7, nDia = 31, abrev = 'jul.', nome = 'julho', alias = { 'jul.', 'july' } },
{ num = 8, nDia = 31, abrev = 'ago.', nome = 'agosto', alias = { 'ago', 'august' } },
{ num = 9, nDia = 30, abrev = 'set.', nome = 'setembro', alias = { 'set', 'set.', 'setembro', 'september' } },
{ num = 10, nDia = 31, abrev = 'out.', nome = 'outubro', alias = { 'out', 'out.', 'october' } },
{ num = 11, nDia = 30, abrev = 'nov.', nome = 'novembro', alias = { 'nov', 'nov.', 'november' } },
{ num = 12, nDia = 31, abrev = 'dez.', nome = 'dezembro', alias = { 'dezembro', 'dez.', 'dez', 'december' } },
}
-- adicionar nomes, abreviaturas e aliases como uma lista de keyMonth listaMes
for i = 1, 12 do
local mes = listaMes[ i ]
listaMes[ tostring( i ) ] = mes
listaMes[ '0' .. i ] = mes
listaMes[ mes.nome ] = mes
listaMes[ mes.abrev ] = mes
for _, n in ipairs( mes.alias ) do
listaMes[ n ] = mes
end
end
--for _, n in ipairs( listaMes.aout.alias ) do
-- listaMes[ n ] = listaMes.aout
--end
fun.listaMes = listaMes
local lista_estacao = {
{ 'Primavera', 'spring', },
{ 'Verão', 'summer', },
{ 'Outono', 'autumn', },
{ 'Inverno', 'winter', },
}
---
-- validadar que a string passada é uma valida.
-- devolver o nome completo ou nil se não for reconhecido
-- se reconhecido, também retorna o número de mes [1-12]
function fun.validaMes( mes )
local m = trim( mes )
if m then
m = mw.ustring.lower( m )
if listaMes[ m ] then
return listaMes[ m ].nome, listaMes[ m ].num
end
end
end
---
-- validar que a string passada é uma estação valida.
-- devolver o nome completo ou nil se não for reconhecido
function fun.validaEstacao( estacao )
local s = trim( estacao )
if s then
s = mw.ustring.lower( s )
for i = 1, 4 do
for _, n in ipairs( lista_estacao[i] ) do
if s == n then
return lista_estacao[i][1]
end
end
end
end
end
---
-- determinationMes encontrar o número do mes e seu nome,
-- do seu nome, seu número ou uma expressão matemática.
-- Se o segundo parâmetro for true, números maiores que 12 ou não inteiros serão aceites.
function fun.determinationMes( mes, mod, laco )
local num, nome
if tonumber( mes ) then
num = math.floor( tonumber( mes ) )
if mod then
-- se o número de mes é calculado por uma expressão, o resultado pode ser maior que 12, ou menor que 1
num = math.fmod( num + 239, 12 ) + 1 -- +239 car fmod(-1) = -1 et non 11
elseif num < 1 or num > 12 then
num = nil
end
elseif trim( mes ) then
nome, num = fun.validaMes( mes )
if nome == nil and laco == nil then
-- tente determinar um número com o analisador #expr do Mediawiki.
-- o parâmetro laco evita o loop.
nome, num = fun.determinationMes( mw.getCurrentFrame():callParserFunction( '#expr', mes ), true, true )
end
end
if num and not nome then
nome = listaMes[ num ].nome
end
return nome, num
end
-- função interna para modelData, para determinar se podemos fazer sem ifexitif
local function existData( dataQualificativo, ano, mes )
local data
if mes then
data = dataQualificativo.mes
else
data = dataQualificativo.ano
end
if type( data ) ~= 'table' then
-- Se os dados não existem, considera-se que não há link.
return
end
-- o qualificador é substituído pelo do banco de dados, que permite aliases.
local link = ano
if dataQualificativo.qualificativo then
link = link .. ' ' .. dataQualificativo.qualificativo
end
local singular = ano
if mes then
link = mes .. ' de ' .. link
singular = mes .. ' de ' .. ano
end
local vazio = tonumber( data.vazio )
if vazio and ano <= vazio then
-- se o ano está na parte "não", testamos se ainda há um link isolado
if type( data.singular ) == 'table' then
for i, v in ipairs( data.singular ) do
if singular == v or singular == tonumber( v ) then
return link
end
end
end
-- parte não e nenhum link => nada
return nil
elseif type( data.todos ) == 'table' then
local todos1, todos2 = tonumber( data.todos[1] ), tonumber( data.todos[2] )
if todos1 and todos2 and ano >= todos1 and ano <= todos2 then
-- o ano está no partido 'todos' então retornamos o link
return link
end
end
-- o ano não está nem na parte nem na parte de todos, então você tem que testar se a página existe.
local alvoLink = mw.title.new( link )
if alvoLink and alvoLink.exists then
return link
end
end
---
-- Exclui o dia da semana e "o" antes de um dado
function fun.limpezaDia( dia )
if type( dia ) == 'string' then
local nomeDia = { '[Ss]egunda-feira', '[Tt]erça-feira', '[Qq]uarta-feira', '[Qq]uinta-feira', '[Ss]exta-feira',
'[Ss]ábado', '[Dd]omingo', '^ *[Oo]' }
-- local premier = { '<abbr class="abbr" title="[Pp]remier" ?>1<sup>er</sup></abbr>', '1<sup>er</sup>', '1er' }
for i, v in ipairs( nomeDia ) do
dia = dia:gsub( v, '' )
end
-- for i, v in ipairs( premier ) do
-- dia = dia:gsub( v, '1' )
-- end
dia = trim( dia )
end
return dia
end
---
-- Separa uma cadeia de data numa tabela com campos dia, mes e ano.
-- os dados devem conter o mês.
function fun.separationDiaMesAno( data )
data = trim( data )
if data then
local function erro( periode, valor )
return false, '<span class="error">' .. periode .. ' invalida (' .. valor .. ')</span>'
end
local dia, mes, ano, esconderMes, esconderAno, separador
-- variável para construir as regex
local j = '([0-3]?%d)' -- dia
local m = '([01]?%d)' -- mês numérico
local mmm = '([^%s%p%d]+[.]?)' -- mês em todas as letras
local aj = '(%-?%d+)' -- ano ou dia
local s = '[ ./-de]+' -- separador simples
-- local sep = '([ ./-de]+)' -- separador com capture, para detectá-lo duas vezes que não é necesário
local menos = '(%-?)' -- o sinal menos para indicar que esses dados não devem ser exibidos
local regexb = {
jmmm = '^'..j..s..mmm..menos..'$',
mmmjva = '^'..mmm..s..j..', ?'..aj..'$',
}
data = fun.limpezaDia( data )
-- excluir categoria, links, tags
data = mw.ustring.gsub( data, '%[%[[Cc]ategor[yi]a?:.-%]%]', '' )
data = data :gsub( '%b<>', '' )
:gsub( '%[%[([^%[%]|]*)|?([^%[%]]*)%]%]', function ( l, t ) return trim( t ) or l end )
-- remoção de espaços não quebráveis
-- nbsp
:gsub( '\194\160', ' ' )
:gsub( ' ', ' ' )
:gsub( ' ', ' ' )
-- narrow nbsp
:gsub( '\226\128\175', ' ' )
:gsub( ' ', ' ' )
-- thin space
:gsub( '\226\128\137', ' ' )
:gsub( ' ', ' ' )
:gsub( ' ', ' ' )
-- simple space
:gsub( ' ', ' ' )
-- vários espaços
:gsub( ' +', ' ' )
-- redução a.C. para simplificar um pouco de regex:
:gsub( '(%d+) ?[Aa]%.? ?C%.?', '-%1' )
-- exclusão de horas em dados ISO
:gsub( '^+?([%d-]*%d%d%-%d%d)T%d%d[%d:,.+-]*Z?$' , '%1')
-- teste de um ano
if data:match( '^'..aj..'$' ) then
ano = data:match( '^'..aj..'$' )
elseif data:match( '^'..aj..s..aj..menos..'$' ) then
-- dd/mm, mm/aaaa ou aaaa/mm
local a, separador, b, sb = data:match( '^'..aj..s..aj..menos..'$' )
a, b = tonumber( a ), tonumber( b )
if separador:match( '^.+%-$' ) then
-- provavelmente mm/-aaaa, ano a.C.
b = 0 - b
end
if a > 12 and ( b < 1 or b > 31 ) or
b > 12 and ( a < 1 or a > 31 ) then
return erro( 'Data', data )
elseif b < 1 or b > 31 then
mes, ano, esconderAno = a, b, sb
elseif a < 1 or a > 31 then
ano, mes = a, b
elseif b > 12 then
return erro( 'Mes', b )
else
dia, mes, esconderMes = a, b, sb
end
elseif data:match( '^'..aj..s..m..menos..'%2'..s..aj..menos..'$' ) then
-- dd/mm/aaaa ou aaaa/mm/dd
dia, separador, mes, esconderMes, ano, esconderAno = data:match( '^'..aj..s..m..menos..'%2'..s..aj..menos..'$' )
if separador == '-' and esconderMes == '-' and esconderAno == '' and tonumber( ano ) > 0 then
-- data no formato dd-mm--aaaa type 17-06--44 para 17 junho 44 a.C.
esconderMes = nil
ano = 0 - ano
end
elseif data:match( '^'..j..s..mmm..menos..'%2'..s..aj..menos..'$' ) then
-- dd mmm aaaa
dia, separador, mes, esconderMes, separador, ano, esconderAno = data:match( '^'..j..s..mmm..menos..'%2'..s..aj..menos..'$' )
elseif data:match( '^'..mmm..s..aj..menos..'$' ) then
-- mmm aaaa
mes, separador, ano, esconderAno = data:match( '^'..mmm..s..aj..menos..'$' )
if separador:match( '^.+%-$' ) then
ano = '-' .. ano
end
elseif data:match( '^'..j..s..mmm..menos..'$' ) then
-- dd mmmm
dia, mes, esconderMes = data:match( '^'..j..s..mmm..menos..'$' )
elseif data:match( '^'..mmm..s..j..', ?'..aj..'$') then
-- mmm dd, aaaa (formato anglo-saxão)
mes, dia, ano = data:match( '^'..mmm..s..j..', ?'..aj..'$')
elseif data:match( '^'..mmm..'$' ) then
mes = data
else
return erro( 'Data', data )
end
local jn, an = tonumber( dia ), tonumber( ano )
if jn and an and ( jn > 31 or jn < 0 or #dia >= 3 ) and an <= 31 then
-- caso particular dos dados ISO 2015-06-17, -0044-06-17 e -0002-06-17
-- inversão do dia e do ano
local temp = ano
ano = dia
dia = temp
end
return fun.validationDiaMesAno{
dia, mes, ano,
esconderAno = trim( esconderAno ) and true or nil,
esconderMes = ( trim( esconderAno ) or not ano ) and trim( esconderMes ) and true or nil,
-- or nil serve apenas para evitar arrastar um valor falso em todos os testes unitários.
}
else
return true, {}
end
end
---
-- validationDiaMesAno verifica os parâmetros correspondentes a uma cadeia valida de dados.
-- os dados podem estar nos parâmetros 1 a 3, ou nos parâmetros dia, mes e ano.
-- A função retorna true seguida por uma tabela com os dados em parâmetros nomeados (sem foco no ano)
-- ou falso seguido por uma mensagem de erro.
function fun.validationDiaMesAno( frame, ... )
local args = Ferramentas.extractArgs( frame, ... )
local dia, mes, numMes, ano
local bdia = args[1] or args['dia'] or ''
local bmes = tostring( args[2] or args['mês'] or args['mes'] or '' )
local bano = args[3] or args['ano'] or args['year'] or ''
local function erro( periode, valor )
return false, '<span class="error">' .. periode .. ' inválido (' .. valor .. ')</span>'
end
-- agora tratamos o ano
if Ferramentas.notEmpty( bano ) then
ano = tonumber( bano )
if ano == nil and type( bano ) == 'string' then
-- teste se o ano contiver a.C.
ano = string.match( string.upper( bano ), '^(%d+) ?[Aa]%.? ?[Cc]%.?' )
ano = tonumber( ano )
if ano then
ano = 0 - ano
else
return erro( 'Ano', bano )
end
elseif ano == 0 then
return erro( 'Ano', 0 )
end
else
ano = nil
end
-- agora tratamos o mês
if Ferramentas.notEmpty( bmes ) then
mes, numMes = fun.determinationMes( bmes )
if mes == nil then
mes = fun.validaEstacao( bmes )
if mes == nil then
return erro( 'Mês', bmes )
end
else
-- agora tratamos o dias se está informado
if Ferramentas.notEmpty( bdia ) then
dia = tonumber( bdia )
if dia == nil then
dia = tonumber( fun.limpezaDia( bdia ) )
end
if dia == nil then
return erro( 'Dia', bdia )
end
-- agora verifica se dia está bem
if dia < 1 or dia > 31 then
return erro( 'Dia', bdia )
elseif dia > listaMes[numMes].nDia then
return erro( 'Dia', bdia .. ' ' .. mes )
elseif dia == 29 and numMes == 2 and ano and ( math.fmod( ano, 4 ) ~= 0 ) then
--o ano bisexto nos séculos é de todos os dias aceite para ser compatível com dados julianos.
return erro( 'Dia', '29 de fevereiro de ' .. ano )
end
else
-- Se não houver dia, a pessoa olha se a primeira letra do mes é minúscula
if bmes:match( '^%u' ) then
-- sim, passamos a primeira letra em letras minúsculas
-- mes = lcfirst( mes )
end
-- se não houver ano, retornamos o mês simples
end
end
else
-- verificamos o dia se está informado
if Ferramentas.notEmpty( bdia ) then
if ano then
return erro( 'Mês', 'não informado' )
else
bdia = fun.limpezaDia( bdia )
dia = tonumber( bdia )
if dia then
if dia > 31 or dia < 1 then
ano = dia
dia = nil
else
return erro( 'Data', 'dia único : ' .. bdia )
end
else
return erro( 'Dia', bdia )
end
end
end
end
-- verificação da ausência de desvio
if ano and ano < 13 and ano > 0 and not dia and ( tonumber( bmes ) or (not mes and tonumber( args[4] ) ) ) then
return false, '<span class="error">ano improvável (' .. ano .. ')</span>'
end
local resultado = {
dia = dia,
mes = mes,
numMes = numMes,
ano = ano,
esconderAno = args.esconderano,
esconderMes = args.escondermes,
}
return true, resultado
end
---
-- emula a predefinição {{tl|Data}}.
-- Configurações:
-- 1: dia (número) ou os dados completos
-- 2: mês (na íntegra) ou estação do ano
-- 3: ano (número)
-- 4: estação do ano
-- juliano: dados no calendário juliano
-- compacto: exibe o mês como uma abreviatura
-- ad: não para desativar a exibição de "a.C." para dados negativos
-- idade: adicione a duração desde que esses dados
-- nolink: não coloque um link nos dados
-- nascimento: adicione a classe "bday"
-- dead: adicione a classe "dday"
function fun.modeloData( frame )
local args = Ferramentas.extractArgs( frame )
local cat, resultado = ''
-- analisar parâmetros sem nome (ou parâmetros de dados dia, mês, ano)
local test, params
local arg1, arg2, arg3 = fun.limpezaDia( args[1] ), trim( args[2] ), trim( args[3] )
if type( arg1 ) == 'string' and arg3 == nil and ( arg1:match( '[^ ./-][ ./-]+[^ ./-]' ) or arg2 == nil or dataLinks[arg2] or mw.ustring.match( arg2, '%a %a' ) ) then
-- os dados estão no primeiro parâmetro
test, params = fun.separationDiaMesAno( arg1 )
if test then
params.qualificativo = arg2
end
else
local function esconderParam( p )
-- separa o possível sinal de menos significando que o parâmetro não deve ser exibido.
if type( p ) ~= 'string' then
return p, nil
end
local value, mask = p:match( '^%s*(.-)(%-?)%s*$' )
return value, ( mask == '-' or nil )
end
local cleanArgs = { arg1 or args.dia }
cleanArgs[2], cleanArgs.escondermes = esconderParam( args[2] or args.mes )
cleanArgs[3], cleanArgs.esconderano = esconderParam( args[3] or args.ano )
test, params = fun.validationDiaMesAno( cleanArgs )
if test then
params.qualificativo = trim( args[4] )
end
end
-- analisar os parâmetros nomeados
if test then
local Yesno = require 'Módulo:Yesno'
params.qualificativo = params.qualificativo or args.qualificativo
-- Juliano pode ter três valores: inativo, formato padrão (true), formato curto
params.juliano = Yesno( args.juliano, 'curto', false )
params.ac = Yesno( args.ac )
local listaParam = {
idade = 'idade',
nascimento = 'nascimento',
morte = 'morte',
falecido = 'morte',
ac = 'a.C.',
nolinks = 'nolinks',
compacto = 'compacto',
compacta = 'compacto',
}
for n, v in pairs( listaParam ) do
params[v] = params[v] or Yesno( args[n], true, false ) or nil
end
-- saída para testes unitários ou para depurar
if args.debug then
return params
end
resultado = fun._modeloData( params )
else
local namespaceCategorisation = { [0] = true, [4] = true, [10] = true, [14] = true, [100] = true }
if namespaceCategorisation[ mw.title.getCurrentTitle().namespace ] and not Ferramentas.notEmpty( args.nocat ) then
cat = '[[Categoria:!Páginas que usam a predefinição data com erros de sintaxe]]'
end
resultado = params .. cat
end
return resultado or ''
end
function fun._modeloData( args )
local ano, mes, numMes, dia = args.ano, args.mes, args.numMes, args.dia
local qualificativo = args.qualificativo
if ( ano or mes or dia ) == nil then
return
end
-- agora tratamos a idade, o nascimento e a morte
local idade = args['idade'] and fun.idade( ano, numMes, dia )
local nascimento = args.nascimento
local morte = args.morte
-- tratar o calendário
local gano, gmes, gdia = ano, numMes, dia -- dados de acordo com o calendário gregoriano para <hora>
local jano, jmes, jdia = ano, mes, dia -- dados de acordo com o calendário juliano, se necessário
local julianoData, julianoSup, julianoSep -- pode ser usado para exibir os dados de acordo com o calendário juliano
local gregAprMes, gregAprAno, gregFim -- Mensagem do calendário gregoriano quando os dados estão de acordo com o calendário juliano
if ano and dia then
local amj = ano * 10000 + numMes * 100 + dia
if amj < 15821014 then
if ano > 0 then
gano, gmes, gdia = fun.julianToGregorian( ano, numMes, dia )
else
-- Calendário gregoriano proléptico com ano 0.
gano, gmes, gdia = fun.julianToGregorian( ano + 1, numMes, dia )
end
args.juliano = false
elseif args.juliano then
gano, gmes, gdia = fun.julianToGregorian( ano, numMes, dia )
ano, mes, dia = gano, listaMes[gmes].nome, gdia
if args.compacto then
jmes = listaMes[ jmes ].abrev
end
if args.juliano == 'curto' then
julianoData = jdia .. ' ' .. jmes .. ' '
julianoSup = '<sup>[[calendário juliano|jul.]]</sup>'
if jano == ano then
gregAprMes = '<sup>[[calendário gregoriano|greg.]]</sup>'
else
julianoData = julianoData .. jano .. ' '
gregAprAno = '<sup>[[calendário gregoriano|greg.]]</sup>'
end
julianoSep = ' / '
else
julianoData = jdia .. ' ' .. jmes .. ' ' .. jano
julianoSep = ' ('
gregFim = ' [[Mudança para o calendário gregoriano|dentro do calendário gregoriano]])'
end
end
else
if ano and ano < 0 then
gano = gano + 1
end
args.juliano = false
end
-- agora geramos o resultado
-- Declarações de variáveis
local wikiLista = {} -- recebe a mensagem de texto exibida para cada parâmetro
local iso = {} -- recebe o formato de data ISO de cada parâmetro
local textoMes = mes -- mensagem de texto que será exibida (possivelmente a abreviação)
if args.compacto then
if args.nolinks then
textoMes = '<abbr class=abbr title="' .. mes .. '">' .. listaMes[ mes ].abrev .. '</abbr>'
else
textoMes = listaMes[ mes ].abrev
end
end
local dataQualificativo, dataCat
if not args.nolinks then
dataQualificativo = dataLinks[qualificativo or '']
if type( dataQualificativo ) ~= 'table' then
-- se o qualificador não estiver no banco de dados, criamos uma tabela mínima,
-- que vai impor um teste no ano, mas considera que não há link no dia ou no mes
dataQualificativo = { qualificativo = ' ' .. qualificativo, ano = { } }
end
dataCat = dataLinks[dataQualificativo.cat]
if type( dataCat ) ~= 'table' or dataCat == dataQualificativo then
dataCat = { qualificativo = '' }
end
end
local function wikiLink( link, texto )
if link == texto then
return '[[' .. texto .. ']]'
else
return '[[' .. link .. '|' .. texto .. ']]'
end
end
-- o dia se informado
local qualifDia = ''
if dia then
local textoDia = dia
if args.nolinks then
table.insert( wikiLista, dia )
else
qualifDia = dataQualificativo.dia and dataQualificativo.qualificativo
or dataCat.dia and dataCat.qualificativo
or ''
local link = dia .. ' de ' .. mes .. ' ' .. qualifDia
-- se não houver um link no mes, ele será exibido com o dia.
table.insert( wikiLista, wikiLink( link, dia ) )
table.insert( wikiLista, wikiLink( link, dia .. ' de '.. textoMes ) )
end
table.insert( iso, 1, string.sub( '0' .. gdia, -2 ) )
end
-- o mês
if mes then
if #wikiLista == 0 and ano == nil then
return textoMes
end
if args.nolinks then
if not args.escondermes then
table.insert( wikiLista, textoMes )
end
else
local link
if ano then
link = existData( dataQualificativo, ano, mes ) or existData( dataCat, ano, mes )
if link == nil and qualificativo and qualifDia == '' then
-- teste novo teste sem o qualificador somente se não houver efemérides para esse qualificador.
link = existData( dataLinks[''], ano, mes )
end
end
if link or args.escondermes then
-- se houver um link, remova o link que exibe 'dia mes' para adicionar 'Mês dia'
table.remove( wikiLista )
if not args.escondermes then
table.insert( wikiLista, wikiLink( link, textoMes ) )
end
elseif #wikiLista > 0 then
-- caso contrário, removemos o link exibindo 'dia' para manter apenas o link 'dia mês'
table.remove( wikiLista, #wikiLista - 1 )
elseif args.esconderano then
-- se não houver dia e o ano não for exibido, insira o único.
table.insert( wikiLista, textoMes )
end
end
if gmes then
table.insert( iso, 1, string.sub( '0' .. gmes, -2 ) )
-- table.insert( wikiLista, ' de ' )
end
table.insert( wikiLista, gregAprMes )
end
-- o ano
if ano and not (args.juliano == true and args.nolinks and jano == ano ) then
if not args.esconderano then
local textoAno = ano
local link
if ano < 0 then
local anoaC = 0 - ano
link = link or ( anoaC .. ' a.C.' )
if args.ac == false then
textoAno = anoaC
else
textoAno = anoaC .. ' <abbr class="abbr" title="'
.. anoaC .. ' antes da Era Comum">a.C.</abbr>'
end
elseif args.ac then
textoAno = textoAno .. ' <abbr class="abbr" title="'
.. textoAno .. ' depois da Era Comum">depois de a.C.</abbr>'
end
if args.nolinks then -- somente se tivermos que exibi-lo
table.insert( wikiLista, textoAno )
else
link = existData( dataQualificativo, ano ) or existData( dataCat, ano ) or link or ano
if mes and #wikiLista == 0 then
-- se o mes não tiver link e não for exibido com o dia, ele será exibido com o ano.
textoAno = textoMes .. ' de ' .. textoAno
end
table.insert( wikiLista, wikiLink( link, textoAno ) )
end
end
end
if ano then
if gano > 999 then
table.insert( iso, 1, gano )
elseif gano > -1 then
table.insert( iso, 1, string.sub( '000' .. gano , -4 ) )
elseif gano > -999 then
-- Calendário gregoriano proléptico com ano 0.
table.insert( iso, 1, 'U-' .. string.sub( '000' .. ( 0 - gano ), -4 ) )
else
table.insert( iso, 1, 'U' .. gano )
end
end
table.insert( wikiLista, gregAprAno )
-- a idade
if type( idade ) == 'number' and idade >= 0 and ( not nascimento or idade < 120 ) then
if idade == 0 then
idade = '(menos de um ano)'
elseif idade == 1 then
idade = '(1 ano)'
else
idade = '(' .. idade .. ' anos)'
end
else
idade = false
end
-- compilação dos resultados
local wikiTexto = table.concat( wikiLista, ' ' )
local isoTexto = table.concat( iso, '-' )
-- Nós adicionamos um pouco de semântica.
local wikiHtml = mw.html.create( '' )
if julianoData then
wikiHtml:tag( 'span')
:addClass( 'nowrap' )
:attr( 'date-sort-value', isoTexto )
:wikitext( julianoData )
:node( julianoSup )
:done()
:wikitext( julianoSep )
end
local dataHtml = wikiHtml:tag( 'time' )
:wikitext( wikiTexto )
if wikiTexto:match( ' ' ) then
dataHtml:addClass( 'nowrap' )
end
if isoTexto ~= wikiTexto then
dataHtml:attr( 'datetime', isoTexto )
:attr( 'date-sort-value', isoTexto )
end
if not args.nolinks then
dataHtml:addClass( 'date-link' )
end
if nascimento then
dataHtml:addClass( 'bday' )
elseif morte then
dataHtml:addClass( 'dday' )
end
wikiHtml:wikitext( gregFim )
if idade then
wikiHtml:wikitext( ' ' )
:tag( 'span' )
:addClass( 'noprint')
:wikitext( idade )
:done()
end
return tostring( wikiHtml )
end
---
-- função para infoboxes, especialmente para exibir nascimento e dados mortos
-- os links presentes nos dados fornecidos são automaticamente excluídos para gerenciar os casos ou
-- o parâmetro já contém um modelo de dados.
-- Configurações:
-- 1 : type de dados a afixar (nascimento / n, morte / m, ou data / d)
-- 1 : Data ou data de nascimento
-- 2 : Data de morte se tipo n ou m
-- qualificativo = sufixo de páginas de dados para vincular (exemplo: na música)
-- nolinks : não mostrar link
-- préfixe : prefixo para exibir se houver um dia (por padrão '')
-- prefixo sem dia: prefixo a ser exibido se não houver dia (padrão: '')
function fun.dataInfobox( frame )
local args = frame.args
if type( args ) ~= 'table' or not ( args[1] and args[2] ) then
return
end
-- analisarData separa os dados do conteúdo a seguir, exclui os links e, se possível, retorna uma tabela com os anos
local function analisarData( d )
if trim( d ) then
local analisar = d:match( ' ou ') or d:match( 'entre ' ) or d:match( 'para ' ) or d:match( 'depois ' ) or d:match( 'antes ' )
if analisar then
return d
end
analisar = d:match( 'datetime="([%d-]+)"' ) or d
-- separa os dados (com seus links) de uma referência ou conteúdo que começa com um espaço)
local inicio, fim = analisar:match( '(.-%d%d%d%]*%-?)([\127 ].+)' )
if not inicio then
-- separa os dados do conteúdo começando com <br>
inicio, fim = analisar:match( '(.-%d%d%d%]*%-?)(<br ?/?>.+)' )
end
analisar = inicio or analisar
-- excluir links
analisar = analisar:gsub(
'%[%[([^%[%]|]*)|?([^%[%]]*)%]%]',
function ( l, t )
return trim( t ) or l
end
)
local t, r = fun.separationDiaMesAno( analisar )
if t then
return r, fim
else
return d, fim
end
end
end
-- prefixo adiciona um prefixo dependendo da presença ou ausência do dia se o parâmetro "prefixo sem dia" for definido
local function prefix( dataString )
if dataString then
local datetime = dataString:match( 'datetime="([U%d%-]+)"' )
if datetime and datetime:match('%-%d%d%-%d%d') and trim( args['prefixo'] ) then
return args['prefixo'] .. ' ' .. dataString
end
if trim( args['prefixo sem dia'] ) then
return args['prefixo sem dia'] .. ' ' .. dataString
end
end
return dataString
end
local nascimento = args[1]:match( '^n' ) == 'n'
local morte = args[1]:match( '^m' ) or args[1]:match( 'morte' )
local mostrarData, qualificativo = args[2], args[4]
local mostrarDataTab, resultadoData, complementData
local dataNascimento, dataMorte
if morte then
mostrarData = args[3]
end
if not trim( mostrarData ) then
return
end
if mostrarData:match( '</time>' ) then
-- Se houver links, provavelmente já existe um modelo de dados, evite executá-lo uma segunda vez
if ( nascimento or morte ) and ( mostrarData:match( 'wikidata%-linkback' )) then
dataNascimento = analisarData( args[2] )
dataMorte = analisarData( args[3] )
resultadoData = mostrarData
else
return prefix( mostrarData )
end
else
mostrarDataTab, complementData = analisarData( mostrarData )
if type( mostrarDataTab ) ~= 'table' then
return mostrarDataTab
else
if nascimento then
dataNascimento = mostrarDataTab
dataMorte = analisarData( args[3] )
elseif morte then
dataNascimento = analisarData( args[2] )
dataMorte = mostrarDataTab
else
qualificativo = args[3]
end
mostrarDataTab.nascimento = nascimento
mostrarDataTab.morte = morte
mostrarDataTab.qualificativo = args.qualificativo or qualificativo
mostrarDataTab.nolinks = args.nolinks
mostrarDataTab.nocat = args.nocat
mostrarDataTab.juliano = args.juliano
end
end
resultadoData = resultadoData or fun.modeloData( mostrarDataTab )
local idade, prefixIdade, suffixIdade, calculoIdade = '', ' <span class="noprint">(', ')</span>', nil
if nascimento and
dataNascimento and
not dataMorte and
type( dataNascimento ) == 'table'
then
calculoIdade = fun.idade( dataNascimento.ano, dataNascimento.numMes, dataNascimento.dia )
if calculoIdade and calculoIdade > 120 then
calculoIdade = nil
end
elseif morte and
dataNascimento and
dataMorte and
type( dataNascimento ) == 'table'
and type( dataMorte ) == 'table'
then
calculoIdade = fun.idade(
dataNascimento.ano,
dataNascimento.numMes,
dataNascimento.dia,
dataMorte.ano,
dataMorte.numMes,
dataMorte.dia
)
prefixIdade = ' (a '
suffixIdade = ')'
end
if tonumber( calculoIdade ) then
if calculoIdade > 1 then
idade = prefixIdade .. calculoIdade .. ' anos' .. suffixIdade
elseif calculoIdade == 1 then
idade = prefixIdade .. 'um ano' .. suffixIdade
elseif calculoIdade == 0 then
idade = prefixIdade .. 'menos de um ano' .. suffixIdade
end
if complementData and complementData:match( 'anos?%)' ) then
complementData = ''
end
end
return prefix( resultadoData ) .. ( complementData or '' ) .. idade
end
---
-- a função dataISO retorna um dado no formato aaaa-mm-dd (sem links)
-- o ano pode ser na forma 2013 ou [[2013 na literatura|2013]]
-- o mês pode estar em letra ou em número
-- o dia pode estar no formato '5', ou 'Sexta 13'
function fun.dataISO( frame )
local args = Ferramentas.extractArgs( frame )
local ano = Ferramentas.notEmpty( args.ano, args.year, args.data )
-- extração do ano
if type( ano ) == 'string' then
ano = ( tonumber( ano ) -- match '2013'
or string.match ( ano, '%D(%d%d%d%d)%D' ) -- match '[[2013 na música|2013]]'
or string.match ( ano, '%D(%d%d%d%d)%D$' ) -- match '17 de setembro de 2013'
or string.match ( ano, '^(%d%d%d%d)%D' ) -- match '2013-09-17'
)
end
ano = tonumber( ano )
-- O formato iso de dados é definido de acordo com o calendário gregoriano.
-- Antes do ano de 1583 os dados são calendários é provavelmente do calendário juliano,
-- então se abstenha.
if ano and ano > 1582 then
local mes = Ferramentas.notEmpty( args.mes, args.month )
-- num mês encontra o número de mês, seja númerico ou texto, completo ou abreviado.
local nomeMes, numMes = fun.determinationMes( mes )
if numMes then
mes = '-' .. string.sub( '0' .. numMes, -2 )
local dia = Ferramentas.notEmpty( args.dia, args.day, args['calendário'] )
if type( dia ) == 'string' then
dia = tonumber( dia ) or tonumber( string.match ( dia, '%d+') )
end
dia = tonumber( dia )
if dia and dia <= listaMes[numMes].nDia then
dia = '-' .. string.sub( '0' .. dia, -2 )
return ano .. mes .. dia
else
return ano .. mes
end
else
return tostring( ano )
end
end
end
---
-- Rank do dia no ano
-- Uso: do_dayRank {ano, meu, dia}
function fun.do_dayRank(arguments)
local yr = tonumber(arguments.year or arguments[1]) or 1
local mt = tonumber(arguments.month or arguments[2]) or 1
local dy = tonumber(arguments.day or arguments[3]) or 1
-- Classificações do primeiro do mês
local ranks = {0,31,59,90,120,151,181,212,243,273,304,334}
local rank = (ranks[mt] or 0) + dy - 1
if(fun.isLeapYear(yr) and (mt >= 3)) then
rank = rank+1
end
return rank
end
-- Número de dias entre dois anos (de 1 de janeiro a 1 de janeiro)
-- Segue o calendário gregoriano
function fun.do_daysBetween(arguments)
local yr1 = tonumber(arguments[1]) or 0
local yr2 = tonumber(arguments[2]) or 0
return fun.daysSinceOrigin(yr2) - fun.daysSinceOrigin(yr1)
end
-- Número de dias desde o ano 1 (de 1 de janeiro a 1 de janeiro)
function fun.daysSinceOrigin(year)
local yr = year-1
return 365*yr + math.floor(yr/4) - math.floor(yr/100) + math.floor(yr/400)
end
-- Teste do ano bissexto (segue o calendário gregoriano)
function fun.isLeapYear(year)
local yr = tonumber(year) or 1
return (yr%4 == 0) and ((yr%100 ~= 0) or (yr%400 == 0))
end
-- Convertendo um número em algarismos romanos
function fun.toRoman(number)
local n = math.floor(number)
local letters = {"I","V","X","L","C","D","M","",""}
local pattern = {"","0","00","000","01","1","10","100","1000","02"}
local result = ""
if(n<=0 or n>=4000) then
result = "---"
else
for i=1,7,2 do
local p = pattern[n%10 + 1]
for j=0,2 do
p = string.gsub(p,tostring(j),letters[i+j])
end
result = p .. result
n = math.floor(n/10)
end
end
return result
end
---
-- Calculando um dado no calendário republicano
-- Supõe-se que os anos 4n + 3 são mais sextiles (3, 7, 11 ...)
function fun.do_toRepCal(arguments)
local yr = tonumber(arguments.year or arguments[1]) or 2000
-- gama absoluto do dia solicitado, sendo o dia 0 ou 22 de setembro de 1792 (1º dia do ano I)
local repDays = fun.do_dayRank(arguments) + fun.do_daysBetween{1792,yr} - fun.do_dayRank{1792,9,22}
local repYear = math.floor((repDays+731)/365.25) - 1
local repDayRank = repDays - 365*(repYear-1) - math.floor(repYear/4)
local repMonth, repDay = math.floor(repDayRank/30)+1, (repDayRank%30)+1
return {repYear, repMonth, repDay}
end
---
-- Ver Predefinição:Idade
-- retorna a idade de acordo com os dados fornecidos. O valor retornado é do tipo 'número'
-- Parâmetros:
-- 1, 2, 3: ano, mês dia de nascimento (suposto no calendário gregoriano)
-- 4, 5, 6: year, mês, dia do cálculo (opcional, por padrão, os dados UTC atuais).
function fun.idade( an, mn, jn, ac, mc, jc )
if ac == nil then
local today = os.date( '!*t' )
ac = today.year
mc = today.month
jc = today.day
else
ac = tonumber( ac )
mc = tonumber( mc )
jc = tonumber( jc )
end
local an = tonumber( an )
local mn = tonumber( mn )
local jn = tonumber( jn )
if an == nil or ac == nil or mn == nil or mc == nil then
-- nenhuma mensagem de erro que possa travar a função de chamada
-- para ela gerenciar esse retorno.
return
end
local idade = ac - an
if mc == mn then
if jc == nil or jn == nil then
return
end
return idade-tonumber( jc < jn and 1 or 0 )
else
return idade-tonumber( mc < mn and 1 or 0 )
end
end
function fun.modeloIdade( frame )
local args = frame.getParent().args
local idade = fun.idade (
args[1] or args['ano'],
args[2] or args['mês'] or args['mes'],
args[3] or args['dia'],
args[4],
args[5],
args[6]
)
if idade then
return idade
else
return '<span class="error">Parâmetro incorretos ou insuficientes para calcular a precisão da idade</span>'
end
end
---
-- calcula o dia juliano à partir de uma data do calendário gregoriano
function fun.julianDay( year, month, day, hour, min, sec )
local julian
julian = math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) * 1461 / 4 )
- math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) / 100 )
+ math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) / 400 )
+ math.floor( ( math.fmod( month + 57609, 12 ) + 4 ) * 153 / 5 )
+ day + ( hour or 12 ) / 24 + ( min or 0 ) / 1440 + ( sec or 0 ) / 86400
- 32167.5
return julian
end
---
-- cálculo do dia juliano a partir de um dado do calendário juliano
function fun.julianDayJulian( year, month, day, hour, min, sec )
local julian
julian = math.floor( math.floor( ( year * 12 + month + 57609 ) / 12 - 1 ) * 1461 / 4 )
+ math.floor( ( math.fmod( month + 57609, 12 ) + 4 ) * 153 / 5 )
+ day + ( hour or 12 ) / 24 + ( min or 0 ) / 1440 + ( sec or 0 ) / 86400
- 32205.5
return julian
end
---
-- cálculo de um dado no calendário gregoriano do dia juliano
function fun.julianDayToGregorian( julianDay )
local base = math.floor( julianDay + 32044.5 ) -- 1 March -4800 (proleptic Gregorian data)
local nCentury = math.floor( ( base * 4 + 3 ) / 146097 )
local sinceCentury = base - math.floor( nCentury * 146097 / 4 )
local nYear = math.floor( ( sinceCentury * 4 + 3 ) / 1461 )
local sinceYear = sinceCentury - math.floor( nYear * 1461 / 4 )
local nMonth = math.floor( ( sinceYear * 5 + 2 ) / 153 )
local day = sinceYear - math.floor( ( nMonth * 153 + 2 ) / 5 ) + 1
local month = nMonth - math.floor( nMonth / 10 ) * 12 + 3
local year = math.floor( sinceYear / 306 ) + nYear + 100 * nCentury - 4800
return year, month, day
end
---
-- cálculo de um dado no calendário juliano do dia juliano
function fun.julianDayToJulian( julianDay )
local year = math.modf( ( julianDay * 4 - 6884469 ) / 1461 )
local r2 = julianDay - math.modf( ( 1461 * year + 6884472 ) / 4 )
local month = math.modf( ( 5 * r2 + 461 ) / 153 )
local day = r2 - math.modf( ( 153 * month - 457 ) / 5 ) + 1
if month > 12 then
year = year + 1
month = month - 12
end
return year, month, day
end
---
-- cálculo de um dado no calendário gregoriano a partir de um dado no calendário juliano
function fun.julianToGregorian( year, month, day )
return fun.julianDayToGregorian( fun.julianDayJulian( year, month, day ) )
end
---
-- cálculo de um dado no calendário juliano a partir de um dado no calendário gregoriano
function fun.gregorianToJulian( year, month, day )
year = tonumber(year)
if month then month = tonumber(month) else month = 6 end --leva um valor central para dar um melhor "palpite"
if day then day = tonumber(day) else day = 15 end
return fun.julianDayToJulian( fun.julianDay( year, month, day ) )
end
--[[
Esta função devolve "CET" ou "CEST" dependendo se no pseudo timezone atual
é hora de verão ou inverno.
Esta função só faz sentido para predefinições usados na Europa
Parâmetro opcional sem nome: "sem link": retorna o texto CET / CEST. caso contrário
retornar o mesmo texto com um wikilink para os artigos correspondentes
--]]
function fun.CEST(frame)
-- opção : não crie wikilink
local opt = trim(frame.args[1] or frame:getParent().args[1])
-- recuperamos as informações na zona atual
local t = mw.getContentLanguage():formatDate("I", nil, true)
if (t == "1") then -- hora de Verão
if (opt == "sem link") then
return "CEST"
elseif (opt == "desvio") then
return "2"
else
return "[[Horário de Verão da Europa Central|CEST]]"
end
else -- horário de inverno (ou outra área onde não se aplica)
if (opt == "sem link") then
return "CET"
elseif (opt == "desvio") then
return "1"
else
return "[[Horário da Europa Central|CET]]"
end
end
end
return fun
|
Index:
pl ar de en es fr it arz nl ja pt ceb sv uk vi war zh ru af ast az bg zh-min-nan bn be ca cs cy da et el eo eu fa gl ko hi hr id he ka la lv lt hu mk ms min no nn ce uz kk ro simple sk sl sr sh fi ta tt th tg azb tr ur zh-yue hy my ace als am an hyw ban bjn map-bms ba be-tarask bcl bpy bar bs br cv nv eml hif fo fy ga gd gu hak ha hsb io ig ilo ia ie os is jv kn ht ku ckb ky mrj lb lij li lmo mai mg ml zh-classical mr xmf mzn cdo mn nap new ne frr oc mhr or as pa pnb ps pms nds crh qu sa sah sco sq scn si sd szl su sw tl shn te bug vec vo wa wuu yi yo diq bat-smg zu lad kbd ang smn ab roa-rup frp arc gn av ay bh bi bo bxr cbk-zam co za dag ary se pdc dv dsb myv ext fur gv gag inh ki glk gan guw xal haw rw kbp pam csb kw km kv koi kg gom ks gcr lo lbe ltg lez nia ln jbo lg mt mi tw mwl mdf mnw nqo fj nah na nds-nl nrm nov om pi pag pap pfl pcd krc kaa ksh rm rue sm sat sc trv stq nso sn cu so srn kab roa-tara tet tpi to chr tum tk tyv udm ug vep fiu-vro vls wo xh zea ty ak bm ch ny ee ff got iu ik kl mad cr pih ami pwn pnt dz rmy rn sg st tn ss ti din chy ts kcg ve
Portal di Ensiklopedia Dunia