<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es">
	<id>https://es.prole.wiki/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=ProleWiki</id>
	<title>ProleWiki - Contribuciones del usuario [es]</title>
	<link rel="self" type="application/atom+xml" href="https://es.prole.wiki/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=ProleWiki"/>
	<link rel="alternate" type="text/html" href="https://es.prole.wiki/wiki/Especial:Contribuciones/ProleWiki"/>
	<updated>2026-10-25T12:42:07Z</updated>
	<subtitle>Contribuciones del usuario</subtitle>
	<generator>MediaWiki 1.43.11</generator>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:InfoboxImage&amp;diff=5449</id>
		<title>Módulo:InfoboxImage</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:InfoboxImage&amp;diff=5449"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Inputs:&lt;br /&gt;
--    image - Can either be a bare filename (with or without the File:/Image: prefix) or a fully formatted image link&lt;br /&gt;
--    page - page to display for multipage images (DjVu)&lt;br /&gt;
--    size - size to display the image&lt;br /&gt;
--    maxsize - maximum size for image&lt;br /&gt;
--    sizedefault - default size to display the image if size param is blank&lt;br /&gt;
--    alt - alt text for image&lt;br /&gt;
--    title - title text for image&lt;br /&gt;
--    border - set to yes if border&lt;br /&gt;
--    center - set to yes, if the image has to be centered&lt;br /&gt;
--    upright - upright image param&lt;br /&gt;
--    suppressplaceholder - if yes then checks to see if image is a placeholder and suppresses it&lt;br /&gt;
--    link - page to visit when clicking on image&lt;br /&gt;
-- Outputs:&lt;br /&gt;
--    Formatted image.&lt;br /&gt;
-- More details available at the &amp;quot;Module:InfoboxImage/doc&amp;quot; page&lt;br /&gt;
&lt;br /&gt;
local i = {};&lt;br /&gt;
&lt;br /&gt;
local placeholder_image = {&lt;br /&gt;
    &amp;quot;Blue - Replace this image female.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Blue - Replace this image male.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Female no free image yet.png&amp;quot;,&lt;br /&gt;
    &amp;quot;Flag of None (square).svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Flag of None.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Flag of.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Green - Replace this image female.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Green - Replace this image male.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Image is needed female.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Image is needed male.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Location map of None.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Male no free image yet.png&amp;quot;,&lt;br /&gt;
    &amp;quot;Missing flag.png&amp;quot;,&lt;br /&gt;
    &amp;quot;No flag.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;No free portrait.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;No portrait (female).svg&amp;quot;,&lt;br /&gt;
    &amp;quot;No portrait (male).svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Red - Replace this image female.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Red - Replace this image male.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Replace this image female (blue).svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Replace this image female.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Replace this image male (blue).svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Replace this image male.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Silver - Replace this image female.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Silver - Replace this image male.svg&amp;quot;,&lt;br /&gt;
    &amp;quot;Replace this image.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;Cricket no pic.png&amp;quot;,&lt;br /&gt;
	&amp;quot;CarersLogo.gif&amp;quot;,&lt;br /&gt;
	&amp;quot;Diagram Needed.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;Example.jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;Image placeholder.png&amp;quot;,&lt;br /&gt;
	&amp;quot;No male portrait.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;Nocover-upload.png&amp;quot;,&lt;br /&gt;
	&amp;quot;NoDVDcover copy.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Noribbon.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;No portrait-BFD-test.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;Placeholder barnstar ribbon.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Project Trains no image.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Image-request.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Sin bandera.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;Sin escudo.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;Replace this image - temple.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Replace this image butterfly.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Replace this image.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;Replace this image1.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;Resolution angle.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Image-No portrait-text-BFD-test.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;Insert image here.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;No image available.png&amp;quot;,&lt;br /&gt;
	&amp;quot;NO IMAGE YET square.png&amp;quot;,&lt;br /&gt;
	&amp;quot;NO IMAGE YET.png&amp;quot;,&lt;br /&gt;
	&amp;quot;No Photo Available.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;No Screenshot.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;No-image-available.jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;Null.png&amp;quot;,&lt;br /&gt;
	&amp;quot;PictureNeeded.gif&amp;quot;,&lt;br /&gt;
	&amp;quot;Place holder.jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;Unbenannt.JPG&amp;quot;,&lt;br /&gt;
	&amp;quot;UploadACopyrightFreeImage.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;UploadAnImage.gif&amp;quot;,&lt;br /&gt;
	&amp;quot;UploadAnImage.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;UploadAnImageShort.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;CarersLogo.gif&amp;quot;,&lt;br /&gt;
	&amp;quot;Diagram Needed.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;No male portrait.svg&amp;quot;,&lt;br /&gt;
	&amp;quot;NoDVDcover copy.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Placeholder barnstar ribbon.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Project Trains no image.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Image-request.png&amp;quot;,&lt;br /&gt;
	&amp;quot;Noimage.gif&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function i.IsPlaceholder(image)&lt;br /&gt;
    -- change underscores to spaces&lt;br /&gt;
    image = mw.ustring.gsub(image, &amp;quot;_&amp;quot;, &amp;quot; &amp;quot;);&lt;br /&gt;
    assert(image ~= nil, &#039;mw.ustring.gsub(image, &amp;quot;_&amp;quot;, &amp;quot; &amp;quot;) must not return nil&#039;)&lt;br /&gt;
    -- if image starts with [[ then remove that and anything after |&lt;br /&gt;
    if mw.ustring.sub(image,1,2) == &amp;quot;[[&amp;quot; then&lt;br /&gt;
        image = mw.ustring.sub(image,3);&lt;br /&gt;
        image = mw.ustring.gsub(image, &amp;quot;([^|]*)|.*&amp;quot;, &amp;quot;%1&amp;quot;);&lt;br /&gt;
        assert(image ~= nil, &#039;mw.ustring.gsub(image, &amp;quot;([^|]*)|.*&amp;quot;, &amp;quot;%1&amp;quot;) must not return nil&#039;)&lt;br /&gt;
    end&lt;br /&gt;
    -- Trim spaces&lt;br /&gt;
    image = mw.ustring.gsub(image, &#039;^[ ]*(.-)[ ]*$&#039;, &#039;%1&#039;);&lt;br /&gt;
    assert(image ~= nil, &amp;quot;mw.ustring.gsub(image, &#039;^[ ]*(.-)[ ]*$&#039;, &#039;%1&#039;) must not return nil&amp;quot;)&lt;br /&gt;
    -- remove prefix if exists&lt;br /&gt;
    local allNames = mw.site.namespaces[6].aliases&lt;br /&gt;
    allNames[#allNames + 1] = mw.site.namespaces[6].name&lt;br /&gt;
    allNames[#allNames + 1] = mw.site.namespaces[6].canonicalName&lt;br /&gt;
    for i, name in ipairs(allNames) do&lt;br /&gt;
        if mw.ustring.lower(mw.ustring.sub(image, 1, mw.ustring.len(name) + 1)) == mw.ustring.lower(name .. &amp;quot;:&amp;quot;) then&lt;br /&gt;
            image = mw.ustring.sub(image, mw.ustring.len(name) + 2);&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    -- Trim spaces&lt;br /&gt;
    image = mw.ustring.gsub(image, &#039;^[ ]*(.-)[ ]*$&#039;, &#039;%1&#039;);&lt;br /&gt;
    -- capitalise first letter&lt;br /&gt;
    image = mw.ustring.upper(mw.ustring.sub(image,1,1)) .. mw.ustring.sub(image,2);&lt;br /&gt;
&lt;br /&gt;
    for i,j in pairs(placeholder_image) do&lt;br /&gt;
        if image == j then&lt;br /&gt;
            return true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function i.InfoboxImage(frame)&lt;br /&gt;
    local image = frame.args[&amp;quot;image&amp;quot;];&lt;br /&gt;
    &lt;br /&gt;
    if image == &amp;quot;&amp;quot; or image == nil then&lt;br /&gt;
        return &amp;quot;&amp;quot;;&lt;br /&gt;
    end&lt;br /&gt;
    if image == &amp;quot;&amp;amp;nbsp;&amp;quot; then&lt;br /&gt;
        return image;&lt;br /&gt;
    end&lt;br /&gt;
    if frame.args[&amp;quot;suppressplaceholder&amp;quot;] ~= &amp;quot;no&amp;quot; then&lt;br /&gt;
        if i.IsPlaceholder(image) == true then&lt;br /&gt;
            return &amp;quot;&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if mw.ustring.lower(mw.ustring.sub(image,1,5)) == &amp;quot;http:&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;;&lt;br /&gt;
    end&lt;br /&gt;
    if mw.ustring.lower(mw.ustring.sub(image,1,6)) == &amp;quot;[http:&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;;&lt;br /&gt;
    end&lt;br /&gt;
    if mw.ustring.lower(mw.ustring.sub(image,1,7)) == &amp;quot;[[http:&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;;&lt;br /&gt;
    end&lt;br /&gt;
    if mw.ustring.lower(mw.ustring.sub(image,1,6)) == &amp;quot;https:&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;;&lt;br /&gt;
    end&lt;br /&gt;
    if mw.ustring.lower(mw.ustring.sub(image,1,7)) == &amp;quot;[https:&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;;&lt;br /&gt;
    end&lt;br /&gt;
    if mw.ustring.lower(mw.ustring.sub(image,1,8)) == &amp;quot;[[https:&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if mw.ustring.sub(image,1,2) == &amp;quot;[[&amp;quot; then&lt;br /&gt;
        -- search for thumbnail images and add to tracking cat if found&lt;br /&gt;
        local cat = &amp;quot;&amp;quot;;&lt;br /&gt;
        if mw.title.getCurrentTitle().namespace == 0 and (mw.ustring.find(image, &amp;quot;|%s*thumb%s*[|%]]&amp;quot;) or mw.ustring.find(image, &amp;quot;|%s*thumbnail%s*[|%]]&amp;quot;)) then&lt;br /&gt;
            cat = &amp;quot;[[Category:Pages using infoboxes with thumbnail images]]&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
        return image .. cat;&lt;br /&gt;
    elseif mw.ustring.sub(image,1,2) == &amp;quot;{{&amp;quot; and mw.ustring.sub(image,1,3) ~= &amp;quot;{{{&amp;quot; then&lt;br /&gt;
        return image;&lt;br /&gt;
    elseif mw.ustring.sub(image,1,1) == &amp;quot;&amp;lt;&amp;quot; then&lt;br /&gt;
        return image;&lt;br /&gt;
    elseif mw.ustring.sub(image,1,5) == mw.ustring.char(127)..&amp;quot;UNIQ&amp;quot; then&lt;br /&gt;
        -- Found strip marker at begining, so pass don&#039;t process at all&lt;br /&gt;
        return image;&lt;br /&gt;
    elseif mw.ustring.sub(image,4,9) == &amp;quot;`UNIQ-&amp;quot; then&lt;br /&gt;
        -- Found strip marker at begining, so pass don&#039;t process at all&lt;br /&gt;
        return image;&lt;br /&gt;
    else&lt;br /&gt;
        local result = &amp;quot;&amp;quot;;&lt;br /&gt;
        local page = frame.args[&amp;quot;page&amp;quot;];&lt;br /&gt;
        local size = frame.args[&amp;quot;size&amp;quot;];&lt;br /&gt;
        local maxsize = frame.args[&amp;quot;maxsize&amp;quot;];&lt;br /&gt;
        local sizedefault = frame.args[&amp;quot;sizedefault&amp;quot;];&lt;br /&gt;
        local alt = frame.args[&amp;quot;alt&amp;quot;];&lt;br /&gt;
        local link = frame.args[&amp;quot;link&amp;quot;];&lt;br /&gt;
        local title = frame.args[&amp;quot;title&amp;quot;];&lt;br /&gt;
        local border = frame.args[&amp;quot;border&amp;quot;];&lt;br /&gt;
        local upright = frame.args[&amp;quot;upright&amp;quot;] or &amp;quot;&amp;quot;;&lt;br /&gt;
        local thumbtime = frame.args[&amp;quot;thumbtime&amp;quot;] or &amp;quot;&amp;quot;;&lt;br /&gt;
        local center= frame.args[&amp;quot;center&amp;quot;];&lt;br /&gt;
        &lt;br /&gt;
        -- remove prefix if exists&lt;br /&gt;
        local allNames = mw.site.namespaces[6].aliases&lt;br /&gt;
        allNames[#allNames + 1] = mw.site.namespaces[6].name&lt;br /&gt;
        allNames[#allNames + 1] = mw.site.namespaces[6].canonicalName&lt;br /&gt;
        for i, name in ipairs(allNames) do&lt;br /&gt;
            if mw.ustring.lower(mw.ustring.sub(image, 1, mw.ustring.len(name) + 1)) == mw.ustring.lower(name .. &amp;quot;:&amp;quot;) then&lt;br /&gt;
                image = mw.ustring.sub(image, mw.ustring.len(name) + 2);&lt;br /&gt;
                break&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        if maxsize ~= &amp;quot;&amp;quot; and maxsize ~= nil then&lt;br /&gt;
            -- if no sizedefault then set to maxsize&lt;br /&gt;
            if sizedefault == &amp;quot;&amp;quot; or sizedefault == nil then&lt;br /&gt;
                sizedefault = maxsize&lt;br /&gt;
            end&lt;br /&gt;
            -- check to see if size bigger than maxsize&lt;br /&gt;
            if size ~= &amp;quot;&amp;quot; and size ~= nil then&lt;br /&gt;
                local sizenumber = tonumber(mw.ustring.match(size,&amp;quot;%d*&amp;quot;)) or 0;&lt;br /&gt;
                local maxsizenumber = tonumber(mw.ustring.match(maxsize,&amp;quot;%d*&amp;quot;)) or 0;&lt;br /&gt;
                if sizenumber&amp;gt;maxsizenumber and maxsizenumber&amp;gt;0 then&lt;br /&gt;
                    size = maxsize;&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        -- add px to size if just a number&lt;br /&gt;
        if (tonumber(size) or 0) &amp;gt; 0 then&lt;br /&gt;
            size = size .. &amp;quot;px&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
        -- add px to sizedefault if just a number&lt;br /&gt;
        if (tonumber(sizedefault) or 0) &amp;gt; 0 then&lt;br /&gt;
            sizedefault = sizedefault .. &amp;quot;px&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        result = &amp;quot;[[File:&amp;quot; .. image;&lt;br /&gt;
        if page ~= &amp;quot;&amp;quot; and page ~= nil then&lt;br /&gt;
            result = result .. &amp;quot;|page=&amp;quot; .. page;&lt;br /&gt;
        end&lt;br /&gt;
        if size ~= &amp;quot;&amp;quot; and size ~= nil then&lt;br /&gt;
            result = result .. &amp;quot;|&amp;quot; .. size;&lt;br /&gt;
        elseif sizedefault ~= &amp;quot;&amp;quot; and sizedefault ~= nil then&lt;br /&gt;
            result = result .. &amp;quot;|&amp;quot; .. sizedefault;&lt;br /&gt;
        else&lt;br /&gt;
            result = result .. &amp;quot;|frameless&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
        if center == &amp;quot;yes&amp;quot; then&lt;br /&gt;
            result = result .. &amp;quot;|center&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
        if alt ~= &amp;quot;&amp;quot; and alt ~= nil then&lt;br /&gt;
            result = result .. &amp;quot;|alt=&amp;quot; .. alt;&lt;br /&gt;
        end&lt;br /&gt;
        if link ~= &amp;quot;&amp;quot; and link ~= nil then&lt;br /&gt;
            result = result .. &amp;quot;|link=&amp;quot; .. link;&lt;br /&gt;
        end&lt;br /&gt;
        if border == &amp;quot;yes&amp;quot; then&lt;br /&gt;
            result = result .. &amp;quot;|border&amp;quot;;&lt;br /&gt;
        end&lt;br /&gt;
        if upright == &amp;quot;yes&amp;quot; then&lt;br /&gt;
            result = result .. &amp;quot;|upright&amp;quot;;&lt;br /&gt;
        elseif upright ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            result = result .. &amp;quot;|upright=&amp;quot; .. upright;&lt;br /&gt;
        end&lt;br /&gt;
        if thumbtime ~= &amp;quot;&amp;quot; then&lt;br /&gt;
            result = result .. &amp;quot;|thumbtime=&amp;quot; .. thumbtime;&lt;br /&gt;
        end&lt;br /&gt;
        -- if alt value is a keyword then do not use as a description&lt;br /&gt;
        if alt == &amp;quot;thumbnail&amp;quot; or alt == &amp;quot;thumb&amp;quot; or alt == &amp;quot;frameless&amp;quot; or alt == &amp;quot;left&amp;quot; or alt == &amp;quot;center&amp;quot; or alt == &amp;quot;right&amp;quot; or alt == &amp;quot;upright&amp;quot; or alt == &amp;quot;border&amp;quot; or mw.ustring.match(alt or &amp;quot;&amp;quot;, &#039;^[0-9]*px$&#039;, 1) ~= nil then&lt;br /&gt;
            alt = nil;&lt;br /&gt;
        end&lt;br /&gt;
        if title ~= &amp;quot;&amp;quot; and title ~= nil then&lt;br /&gt;
            -- does title param contain any templatestyles? If yes then set to blank.&lt;br /&gt;
            if mw.ustring.match(frame:preprocess(title), &#039;UNIQ%-%-templatestyles&#039;, 1) ~= nil then&lt;br /&gt;
                title = nil;&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        if title ~= &amp;quot;&amp;quot; and title ~= nil then&lt;br /&gt;
            result = result .. &amp;quot;|&amp;quot; .. title;&lt;br /&gt;
        elseif alt ~= &amp;quot;&amp;quot; and alt ~= nil then&lt;br /&gt;
            result = result .. &amp;quot;|&amp;quot; .. alt;&lt;br /&gt;
        end&lt;br /&gt;
        result = result .. &amp;quot;]]&amp;quot;;&lt;br /&gt;
        &lt;br /&gt;
        return result;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return i;&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:String&amp;diff=5447</id>
		<title>Módulo:String</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:String&amp;diff=5447"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[  &lt;br /&gt;
Este módulo está destinado a proporcionar acceso a las funciones de cadena (string) básicas.&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local str = {}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
len&lt;br /&gt;
&lt;br /&gt;
Parametros&lt;br /&gt;
    s: La cadena a encontrar su longitud &lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
function str.len( frame )&lt;br /&gt;
    local new_args = str._getParameters( frame.args, {&#039;s&#039;} );&lt;br /&gt;
    local s = new_args[&#039;s&#039;] or &#039;&#039;;&lt;br /&gt;
    return mw.ustring.len( s )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
sub&lt;br /&gt;
&lt;br /&gt;
Parametros&lt;br /&gt;
    s: La cadena donde extraer la subcadena &lt;br /&gt;
    i: La cadena donde extraer la subcadena.&lt;br /&gt;
    j: Índice final de la subcadena, por defecto la longitud total, hasta el último carácter.&lt;br /&gt;
    &lt;br /&gt;
]]&lt;br /&gt;
function str.sub( frame )&lt;br /&gt;
    local new_args = str._getParameters( frame.args, { &#039;s&#039;, &#039;i&#039;, &#039;j&#039; } );&lt;br /&gt;
    local s = new_args[&#039;s&#039;] or &#039;&#039;;&lt;br /&gt;
    local i = tonumber( new_args[&#039;i&#039;] ) or 1;&lt;br /&gt;
    local j = tonumber( new_args[&#039;j&#039;] ) or -1;&lt;br /&gt;
    &lt;br /&gt;
    local len = mw.ustring.len( s );&lt;br /&gt;
&lt;br /&gt;
    -- Convertir negativos para la comprobación de rango&lt;br /&gt;
    if i &amp;lt; 0 then&lt;br /&gt;
        i = len + i + 1;&lt;br /&gt;
    end&lt;br /&gt;
    if j &amp;lt; 0 then&lt;br /&gt;
        j = len + j + 1;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    if i &amp;gt; len or j &amp;gt; len or i &amp;lt; 1 or j &amp;lt; 1 then&lt;br /&gt;
        return str._error( &#039;Índice fuera del rango de la cadena&#039; );&lt;br /&gt;
    end&lt;br /&gt;
    if j &amp;lt; i then&lt;br /&gt;
        return str._error( &#039;Índices de la cadena no ordenados&#039; );&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return mw.ustring.sub( s, i, j )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
match&lt;br /&gt;
&lt;br /&gt;
Parametros&lt;br /&gt;
   s: cadena donde se hace la búsqueda &lt;br /&gt;
   pattern: patrón o cadena a buscar. &lt;br /&gt;
   start: índice de la cadena dónde empezar a buscar, por defecto 1, el primer carácter. &lt;br /&gt;
   match: si se encuentran múltiples coincidencias, especifica cuál de ellas devolver. Por defecto es 1, l&lt;br /&gt;
       la primera coincidencia encontrada. Un número negativo cuenta desde el final, por lo tanto &lt;br /&gt;
       match = -1 es la última coincidencia. &lt;br /&gt;
   plain: indica si el patrón debe interpretarse como texto limpio, por defecto &#039;false&#039;. nomatch: en caso de &lt;br /&gt;
       no encontrar ninguna coincidencia, devuelve el valor de &amp;quot;nomatch&amp;quot; en lugar de un error. &lt;br /&gt;
       Si el número match o el índice start están fuera del rango de la cadena, entonces la función genera un error. &lt;br /&gt;
       También genera un error si no encuentra ninguna coincidencia. &lt;br /&gt;
       Con el parámetro global ignore_errors = true se suprime el    &lt;br /&gt;
       error y devuelve una cadena vacía.&lt;br /&gt;
]]&lt;br /&gt;
function str.match( frame )&lt;br /&gt;
    local new_args = str._getParameters( frame.args, {&#039;s&#039;, &#039;pattern&#039;, &#039;start&#039;, &#039;match&#039;, &#039;plain&#039;, &#039;nomatch&#039;} );&lt;br /&gt;
    local s = new_args[&#039;s&#039;] or &#039;&#039;;&lt;br /&gt;
    local start = tonumber( new_args[&#039;start&#039;] ) or 1;&lt;br /&gt;
    local plain_flag = str._getBoolean( new_args[&#039;plain&#039;] or false );&lt;br /&gt;
    local pattern = new_args[&#039;pattern&#039;] or &#039;&#039;;&lt;br /&gt;
    local match_index = math.floor( tonumber(new_args[&#039;match&#039;]) or 1 );&lt;br /&gt;
    local nomatch = new_args[&#039;nomatch&#039;];&lt;br /&gt;
    &lt;br /&gt;
    if s == &#039;&#039; then&lt;br /&gt;
        return str._error( &#039;La cadena donde buscar está vacía&#039; );&lt;br /&gt;
    end&lt;br /&gt;
    if pattern == &#039;&#039; then&lt;br /&gt;
        return str._error( &#039;La cadena de búsqueda está vacía &#039; );&lt;br /&gt;
    end&lt;br /&gt;
    if math.abs(start) &amp;lt; 1 or math.abs(start) &amp;gt; mw.ustring.len( s ) then&lt;br /&gt;
        return str._error( &#039;Índice d\&#039;inicio fuera del rango de la cadena &#039; );&lt;br /&gt;
    end&lt;br /&gt;
    if match_index == 0 then&lt;br /&gt;
        return str._error( &#039;Número de coincidencias fuera de rango&#039; );&lt;br /&gt;
    end&lt;br /&gt;
    if plain_flag then&lt;br /&gt;
        pattern = str._escapePattern( pattern );&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local result&lt;br /&gt;
    if match_index == 1 then&lt;br /&gt;
        -- Encontrar la primera coincidencia es un caso sencillo.&lt;br /&gt;
        result = mw.ustring.match( s, pattern, start )&lt;br /&gt;
    else&lt;br /&gt;
        if start &amp;gt; 1 then&lt;br /&gt;
            s = mw.ustring.sub( s, start );&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        local iterator = mw.ustring.gmatch(s, pattern);&lt;br /&gt;
        if match_index &amp;gt; 0 then&lt;br /&gt;
            -- Búsqueda hacia adelante&lt;br /&gt;
            for w in iterator do&lt;br /&gt;
                match_index = match_index - 1;&lt;br /&gt;
                if match_index == 0 then&lt;br /&gt;
                    result = w;&lt;br /&gt;
                    break;&lt;br /&gt;
                end&lt;br /&gt;
            end    &lt;br /&gt;
        else&lt;br /&gt;
            -- Invierte búsqueda&lt;br /&gt;
            local result_table = {};&lt;br /&gt;
            local count = 1;&lt;br /&gt;
            for w in iterator do&lt;br /&gt;
                result_table[count] = w;&lt;br /&gt;
                count = count + 1;&lt;br /&gt;
            end&lt;br /&gt;
            &lt;br /&gt;
            result = result_table[ count + match_index ];            &lt;br /&gt;
        end&lt;br /&gt;
    end        &lt;br /&gt;
    &lt;br /&gt;
    if result == nil then&lt;br /&gt;
        if nomatch == nil then&lt;br /&gt;
            return str._error( &#039;Ninguna coincidencia encontrada&#039; );&lt;br /&gt;
        else&lt;br /&gt;
            return nomatch;&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        return result;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
pos&lt;br /&gt;
&lt;br /&gt;
Parámetros&lt;br /&gt;
   target: Cadena donde buscar. &lt;br /&gt;
   pos: Índice del carácter a devolver. &lt;br /&gt;
]]&lt;br /&gt;
function str.pos( frame )&lt;br /&gt;
    local new_args = str._getParameters( frame.args, {&#039;target&#039;, &#039;pos&#039;} );&lt;br /&gt;
    local target_str = new_args[&#039;target&#039;] or &#039;&#039;;&lt;br /&gt;
    local pos = tonumber( new_args[&#039;pos&#039;] ) or 0;&lt;br /&gt;
&lt;br /&gt;
    if pos == 0 or math.abs(pos) &amp;gt; mw.ustring.len( target_str ) then&lt;br /&gt;
        return str._error( &#039;Índice fuera del rango de la cadena&#039; );&lt;br /&gt;
    end    &lt;br /&gt;
    &lt;br /&gt;
    return mw.ustring.sub( target_str, pos, pos );&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
find&lt;br /&gt;
&lt;br /&gt;
Parametros&lt;br /&gt;
    source: Cadena donde buscar. &lt;br /&gt;
    target: Cadena a buscar o patrón de búsqueda. &lt;br /&gt;
    start: Índice de la cadena fuente donde empezar a buscar, por defecto 1, el primer carácter. &lt;br /&gt;
    plain: Indica si la búsqueda debe interpretarse como texto limpio, de lo contrario como patrón Lua. &lt;br /&gt;
        Por defecto es &#039;true&#039;.&lt;br /&gt;
]]&lt;br /&gt;
function str.find( frame )&lt;br /&gt;
    local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;target&#039;, &#039;start&#039;, &#039;plain&#039; } ); &lt;br /&gt;
    local source_str = new_args[&#039;source&#039;] or &#039;&#039;;&lt;br /&gt;
    local pattern = new_args[&#039;target&#039;] or &#039;&#039;;&lt;br /&gt;
    local start_pos = tonumber(new_args[&#039;start&#039;]) or 1;&lt;br /&gt;
    local plain = new_args[&#039;plain&#039;] or true;&lt;br /&gt;
        &lt;br /&gt;
    if source_str == &#039;&#039; or pattern == &#039;&#039; then&lt;br /&gt;
        return 0;&lt;br /&gt;
    end    &lt;br /&gt;
    &lt;br /&gt;
    plain = str._getBoolean( plain );&lt;br /&gt;
&lt;br /&gt;
    local start = mw.ustring.find( source_str, pattern, start_pos, plain )&lt;br /&gt;
    if start == nil then&lt;br /&gt;
        start = 0&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return start&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
replace&lt;br /&gt;
&lt;br /&gt;
Parámetros&lt;br /&gt;
    source: Cadena donde buscar &lt;br /&gt;
    pattern: Cadena de búsqueda o patrón a buscar &lt;br /&gt;
    replace: Texto de reemplazo &lt;br /&gt;
    count: Número de ocurrencias a reemplazar, por defecto todas. &lt;br /&gt;
    plain: Indica si la búsqueda debe interpretarse como texto limpio, de lo contrario como patrón Lua. Por &lt;br /&gt;
        defecto es &#039;true&#039; &lt;br /&gt;
]]&lt;br /&gt;
function str.replace( frame )&lt;br /&gt;
    local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;pattern&#039;, &#039;replace&#039;, &#039;count&#039;, &#039;plain&#039; } ); &lt;br /&gt;
    local source_str = new_args[&#039;source&#039;] or &#039;&#039;;&lt;br /&gt;
    local pattern = new_args[&#039;pattern&#039;] or &#039;&#039;;&lt;br /&gt;
    local replace = new_args[&#039;replace&#039;] or &#039;&#039;;&lt;br /&gt;
    local count = tonumber( new_args[&#039;count&#039;] );&lt;br /&gt;
    local plain = new_args[&#039;plain&#039;] or true;&lt;br /&gt;
        &lt;br /&gt;
    if source_str == &#039;&#039; or pattern == &#039;&#039; then&lt;br /&gt;
        return source_str;&lt;br /&gt;
    end    &lt;br /&gt;
    plain = str._getBoolean( plain );&lt;br /&gt;
&lt;br /&gt;
    if plain then&lt;br /&gt;
        pattern = str._escapePattern( pattern );&lt;br /&gt;
        replace = mw.ustring.gsub( replace, &amp;quot;%%&amp;quot;, &amp;quot;%%%%&amp;quot; ); --Sólo es necesario secuencias de escape.&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local result;&lt;br /&gt;
&lt;br /&gt;
    if count ~= nil then&lt;br /&gt;
        result = mw.ustring.gsub( source_str, pattern, replace, count );&lt;br /&gt;
    else&lt;br /&gt;
        result = mw.ustring.gsub( source_str, pattern, replace );&lt;br /&gt;
    end        &lt;br /&gt;
&lt;br /&gt;
    return result;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function str.mayuscula(frame) -- Convierte en mayúsculas la primera letra que aparece en la edición de una cadena&lt;br /&gt;
    local s = frame.args[1] or &#039;&#039;;&lt;br /&gt;
    if s  ~= &#039;&#039; then        &lt;br /&gt;
        local cambio = {};&lt;br /&gt;
        local modo = {};&lt;br /&gt;
        if string.find(s, &#039;|&#039;) ~= nil then -- Enlaces con etiqueta&lt;br /&gt;
            modo = string.upper(string.match(s,&#039;(|%a)&#039;));&lt;br /&gt;
            cambio = string.gsub(s,&#039;|%a&#039;, modo,1);&lt;br /&gt;
        elseif string.find(s, &#039;[[]&#039;) ~= nil then -- Enlaces sin etiqueta&lt;br /&gt;
            modo = string.upper(string.match(s,&#039;^(..%a)&#039;));&lt;br /&gt;
            cambio = string.gsub(s,&#039;^..%a&#039;, modo,1);&lt;br /&gt;
        elseif string.match(s,&#039;^%a&#039;) ~= nil then -- Sin enlace&lt;br /&gt;
           modo = string.upper(string.match(s,&#039;^(%a)&#039;));&lt;br /&gt;
           cambio = string.gsub(s,&#039;^%a&#039;, modo, 1);&lt;br /&gt;
        else&lt;br /&gt;
           cambio = s;&lt;br /&gt;
        end&lt;br /&gt;
        return cambio;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Función de ayuda que rellena la lista de argumentos, para que el usuario pueda utilizar una combinación de&lt;br /&gt;
 parámetros con nombre y sin nombre. Esto es importante porque los parámetros con nombre no funcionan igual &lt;br /&gt;
 que los parámetros sin nombre cuando se encadenan recortes, y cuando se trata de cadenas&lt;br /&gt;
 a veces se debe conservar o quitar espacios en blanco dependiendo de la aplicación. &lt;br /&gt;
]]&lt;br /&gt;
function str._getParameters( frame_args, arg_list )&lt;br /&gt;
    local new_args = {};&lt;br /&gt;
    local index = 1;&lt;br /&gt;
    local value;&lt;br /&gt;
    &lt;br /&gt;
    for i,arg in ipairs( arg_list ) do&lt;br /&gt;
        value = frame_args[arg]&lt;br /&gt;
        if value == nil then&lt;br /&gt;
            value = frame_args[index];&lt;br /&gt;
            index = index + 1;&lt;br /&gt;
        end&lt;br /&gt;
        new_args[arg] = value;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return new_args;&lt;br /&gt;
end        &lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Función de ayuda para controlar los mensajes de error.&lt;br /&gt;
]]&lt;br /&gt;
function str._error( error_str )&lt;br /&gt;
    local frame = mw.getCurrentFrame();&lt;br /&gt;
    local error_category = frame.args.error_category or &#039;Errores detectados por el módulo String&#039;;&lt;br /&gt;
    local ignore_errors = frame.args.ignore_errors or false;&lt;br /&gt;
    local no_category = frame.args.no_category or false;&lt;br /&gt;
    &lt;br /&gt;
    if str._getBoolean(ignore_errors) then&lt;br /&gt;
        return &#039;&#039;;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local error_str = &#039;&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;Error del módulo String: &#039; .. error_str .. &#039;&amp;lt;/strong&amp;gt;&#039;;&lt;br /&gt;
    if error_category ~= &#039;&#039; and not str._getBoolean( no_category ) then&lt;br /&gt;
        error_str = &#039;[[Categoría:Wikipedia:&#039; .. error_category .. &#039;]]&#039; .. error_str;&lt;br /&gt;
    end        &lt;br /&gt;
    &lt;br /&gt;
    return error_str;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Función de ayuda para interpretar cadenas booleanas.&lt;br /&gt;
]]&lt;br /&gt;
function str._getBoolean( boolean_str )&lt;br /&gt;
    local boolean_value;&lt;br /&gt;
    &lt;br /&gt;
    if type( boolean_str ) == &#039;string&#039; then&lt;br /&gt;
        boolean_str = boolean_str:lower();&lt;br /&gt;
        if boolean_str == &#039;false&#039; or boolean_str == &#039;no&#039; or boolean_str == &#039;0&#039; &lt;br /&gt;
                or boolean_str == &#039;&#039; then&lt;br /&gt;
            boolean_value = false;&lt;br /&gt;
        else&lt;br /&gt;
            boolean_value = true;&lt;br /&gt;
        end    &lt;br /&gt;
    elseif type( boolean_str ) == &#039;boolean&#039; then&lt;br /&gt;
        boolean_value = boolean_str;&lt;br /&gt;
    else&lt;br /&gt;
        error( &#039;Ningún valor booleano encontrado&#039; );&lt;br /&gt;
    end    &lt;br /&gt;
    return boolean_value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Función de ayuda que escapa a todos los caracteres de patrón para que puedan ser tratados&lt;br /&gt;
como texto sin formato.&lt;br /&gt;
]]&lt;br /&gt;
function str._escapePattern( pattern_str )&lt;br /&gt;
    return mw.ustring.gsub( pattern_str, &amp;quot;([%(%)%.%%%+%-%*%?%[%^%$%]])&amp;quot;, &amp;quot;%%%1&amp;quot; );&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return str&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Infobox&amp;diff=5445</id>
		<title>Módulo:Infobox</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Infobox&amp;diff=5445"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--&lt;br /&gt;
-- This module implements {{Infobox}}&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local navbar = require(&#039;Module:Navbar&#039;)._navbar&lt;br /&gt;
&lt;br /&gt;
local args = {}&lt;br /&gt;
local origArgs = {}&lt;br /&gt;
local root&lt;br /&gt;
&lt;br /&gt;
local function notempty( s ) return s and s:match( &#039;%S&#039; ) end&lt;br /&gt;
&lt;br /&gt;
local function fixChildBoxes(sval, tt)&lt;br /&gt;
	if notempty(sval) then&lt;br /&gt;
		local marker = &#039;&amp;lt;span class=special_infobox_marker&amp;gt;&#039;&lt;br /&gt;
		local s = sval&lt;br /&gt;
		s = mw.ustring.gsub(s, &#039;(&amp;lt;%s*[Tt][Rr])&#039;, marker .. &#039;%1&#039;)&lt;br /&gt;
		s = mw.ustring.gsub(s, &#039;(&amp;lt;/[Tt][Rr]%s*&amp;gt;)&#039;, &#039;%1&#039; .. marker)&lt;br /&gt;
		if s:match(marker) then&lt;br /&gt;
			s = mw.ustring.gsub(s, marker .. &#039;%s*&#039; .. marker, &#039;&#039;)&lt;br /&gt;
			s = mw.ustring.gsub(s, &#039;([\r\n]|-[^\r\n]*[\r\n])%s*&#039; .. marker, &#039;%1&#039;)&lt;br /&gt;
			s = mw.ustring.gsub(s, marker .. &#039;%s*([\r\n]|-)&#039;, &#039;%1&#039;)&lt;br /&gt;
			s = mw.ustring.gsub(s, &#039;(&amp;lt;/[Cc][Aa][Pp][Tt][Ii][Oo][Nn]%s*&amp;gt;%s*)&#039; .. marker, &#039;%1&#039;)&lt;br /&gt;
			s = mw.ustring.gsub(s, &#039;(&amp;lt;%s*[Tt][Aa][Bb][Ll][Ee][^&amp;lt;&amp;gt;]*&amp;gt;%s*)&#039; .. marker, &#039;%1&#039;)&lt;br /&gt;
			s = mw.ustring.gsub(s, &#039;^(%{|[^\r\n]*[\r\n]%s*)&#039; .. marker, &#039;%1&#039;)&lt;br /&gt;
			s = mw.ustring.gsub(s, &#039;([\r\n]%{|[^\r\n]*[\r\n]%s*)&#039; .. marker, &#039;%1&#039;)&lt;br /&gt;
			s = mw.ustring.gsub(s, marker .. &#039;(%s*&amp;lt;/[Tt][Aa][Bb][Ll][Ee]%s*&amp;gt;)&#039;, &#039;%1&#039;)&lt;br /&gt;
			s = mw.ustring.gsub(s, marker .. &#039;(%s*\n|%})&#039;, &#039;%1&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		if s:match(marker) then&lt;br /&gt;
			local subcells = mw.text.split(s, marker)&lt;br /&gt;
			s = &#039;&#039;&lt;br /&gt;
			for k = 1, #subcells do&lt;br /&gt;
				if k == 1 then&lt;br /&gt;
					s = s .. subcells[k] .. &#039;&amp;lt;/&#039; .. tt .. &#039;&amp;gt;&amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
				elseif k == #subcells then&lt;br /&gt;
					local rowstyle = &#039; style=&amp;quot;display:none&amp;quot;&#039;&lt;br /&gt;
					if notempty(subcells[k]) then rowstyle = &#039;&#039;	end&lt;br /&gt;
					s = s .. &#039;&amp;lt;tr&#039; .. rowstyle ..&#039;&amp;gt;&amp;lt;&#039; .. tt .. &#039; colspan=2&amp;gt;\n&#039; .. subcells[k]&lt;br /&gt;
				elseif notempty(subcells[k]) then&lt;br /&gt;
					if (k % 2) == 0 then&lt;br /&gt;
						s = s .. subcells[k]&lt;br /&gt;
					else&lt;br /&gt;
						s = s .. &#039;&amp;lt;tr&amp;gt;&amp;lt;&#039; .. tt .. &#039; colspan=2&amp;gt;\n&#039; .. subcells[k] .. &#039;&amp;lt;/&#039; .. tt .. &#039;&amp;gt;&amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		-- the next two lines add a newline at the end of lists for the PHP parser&lt;br /&gt;
		-- https://en.wikipedia.org/w/index.php?title=Template_talk:Infobox_musical_artist&amp;amp;oldid=849054481&lt;br /&gt;
		-- remove when [[:phab:T191516]] is fixed or OBE&lt;br /&gt;
		s = mw.ustring.gsub(s, &#039;([\r\n][%*#;:][^\r\n]*)$&#039;, &#039;%1\n&#039;)&lt;br /&gt;
		s = mw.ustring.gsub(s, &#039;^([%*#;:][^\r\n]*)$&#039;, &#039;%1\n&#039;)&lt;br /&gt;
		s = mw.ustring.gsub(s, &#039;^([%*#;:])&#039;, &#039;\n%1&#039;)&lt;br /&gt;
		s = mw.ustring.gsub(s, &#039;^(%{%|)&#039;, &#039;\n%1&#039;)&lt;br /&gt;
		return s&lt;br /&gt;
	else&lt;br /&gt;
		return sval&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function union(t1, t2)&lt;br /&gt;
	-- Returns the union of the values of two tables, as a sequence.&lt;br /&gt;
	local vals = {}&lt;br /&gt;
	for k, v in pairs(t1) do&lt;br /&gt;
		vals[v] = true&lt;br /&gt;
	end&lt;br /&gt;
	for k, v in pairs(t2) do&lt;br /&gt;
		vals[v] = true&lt;br /&gt;
	end&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(vals) do&lt;br /&gt;
		table.insert(ret, k)&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getArgNums(prefix)&lt;br /&gt;
	-- Returns a table containing the numbers of the arguments that exist&lt;br /&gt;
	-- for the specified prefix. For example, if the prefix was &#039;data&#039;, and&lt;br /&gt;
	-- &#039;data1&#039;, &#039;data2&#039;, and &#039;data5&#039; exist, it would return {1, 2, 5}.&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		local num = tostring(k):match(&#039;^&#039; .. prefix .. &#039;([1-9]%d*)$&#039;)&lt;br /&gt;
		if num then table.insert(nums, tonumber(num)) end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function addRow(rowArgs)&lt;br /&gt;
	-- Adds a row to the infobox, with either a header cell&lt;br /&gt;
	-- or a label/data cell combination.&lt;br /&gt;
	if rowArgs.header and rowArgs.header ~= &#039;_BLANK_&#039; then&lt;br /&gt;
		root&lt;br /&gt;
			:tag(&#039;tr&#039;)&lt;br /&gt;
				:addClass(rowArgs.rowclass)&lt;br /&gt;
				:cssText(rowArgs.rowstyle)&lt;br /&gt;
				:attr(&#039;id&#039;, rowArgs.rowid)&lt;br /&gt;
				:tag(&#039;th&#039;)&lt;br /&gt;
					:attr(&#039;colspan&#039;, 2)&lt;br /&gt;
					:attr(&#039;id&#039;, rowArgs.headerid)&lt;br /&gt;
					:addClass(rowArgs.class)&lt;br /&gt;
					:addClass(args.headerclass)&lt;br /&gt;
					:css(&#039;text-align&#039;, &#039;center&#039;)&lt;br /&gt;
					:cssText(args.headerstyle)&lt;br /&gt;
					:cssText(rowArgs.rowcellstyle)&lt;br /&gt;
					:wikitext(fixChildBoxes(rowArgs.header, &#039;th&#039;))&lt;br /&gt;
		if rowArgs.data then&lt;br /&gt;
			root:wikitext(&#039;[[Category:Pages which use infobox templates with ignored data cells]]&#039;)&lt;br /&gt;
		end&lt;br /&gt;
	elseif rowArgs.data then&lt;br /&gt;
		if not rowArgs.data:gsub(&#039;%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]&#039;, &#039;&#039;):match(&#039;^%S&#039;) then&lt;br /&gt;
			rowArgs.rowstyle = &#039;display:none&#039;&lt;br /&gt;
		end&lt;br /&gt;
		local row = root:tag(&#039;tr&#039;)&lt;br /&gt;
		row:addClass(rowArgs.rowclass)&lt;br /&gt;
		row:cssText(rowArgs.rowstyle)&lt;br /&gt;
		row:attr(&#039;id&#039;, rowArgs.rowid)&lt;br /&gt;
		if rowArgs.label then&lt;br /&gt;
			row&lt;br /&gt;
				:tag(&#039;th&#039;)&lt;br /&gt;
					:attr(&#039;scope&#039;, &#039;row&#039;)&lt;br /&gt;
					:attr(&#039;id&#039;, rowArgs.labelid)&lt;br /&gt;
					:cssText(args.labelstyle)&lt;br /&gt;
					:cssText(rowArgs.rowcellstyle)&lt;br /&gt;
					:wikitext(rowArgs.label)&lt;br /&gt;
					:done()&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		local dataCell = row:tag(&#039;td&#039;)&lt;br /&gt;
		if not rowArgs.label then&lt;br /&gt;
			dataCell&lt;br /&gt;
				:attr(&#039;colspan&#039;, 2)&lt;br /&gt;
				:css(&#039;text-align&#039;, &#039;center&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		dataCell&lt;br /&gt;
			:attr(&#039;id&#039;, rowArgs.dataid)&lt;br /&gt;
			:addClass(rowArgs.class)&lt;br /&gt;
			:cssText(rowArgs.datastyle)&lt;br /&gt;
			:cssText(rowArgs.rowcellstyle)&lt;br /&gt;
			:wikitext(fixChildBoxes(rowArgs.data, &#039;td&#039;))&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderTitle()&lt;br /&gt;
	if not args.title then return end&lt;br /&gt;
&lt;br /&gt;
	root&lt;br /&gt;
		:tag(&#039;caption&#039;)&lt;br /&gt;
			:addClass(args.titleclass)&lt;br /&gt;
			:cssText(args.titlestyle)&lt;br /&gt;
			:wikitext(args.title)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderAboveRow()&lt;br /&gt;
	if not args.above then return end&lt;br /&gt;
&lt;br /&gt;
	root&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;th&#039;)&lt;br /&gt;
				:attr(&#039;colspan&#039;, 2)&lt;br /&gt;
				:addClass(args.aboveclass)&lt;br /&gt;
				:css(&#039;text-align&#039;, &#039;center&#039;)&lt;br /&gt;
				:css(&#039;font-size&#039;, &#039;125%&#039;)&lt;br /&gt;
				:css(&#039;font-weight&#039;, &#039;bold&#039;)&lt;br /&gt;
				:cssText(args.abovestyle)&lt;br /&gt;
				:wikitext(fixChildBoxes(args.above,&#039;th&#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderBelowRow()&lt;br /&gt;
	if not args.below then return end&lt;br /&gt;
&lt;br /&gt;
	root&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;td&#039;)&lt;br /&gt;
				:attr(&#039;colspan&#039;, &#039;2&#039;)&lt;br /&gt;
				:addClass(args.belowclass)&lt;br /&gt;
				:css(&#039;text-align&#039;, &#039;center&#039;)&lt;br /&gt;
				:cssText(args.belowstyle)&lt;br /&gt;
				:wikitext(fixChildBoxes(args.below,&#039;td&#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderSubheaders()&lt;br /&gt;
	if args.subheader then&lt;br /&gt;
		args.subheader1 = args.subheader&lt;br /&gt;
	end&lt;br /&gt;
	if args.subheaderrowclass then&lt;br /&gt;
		args.subheaderrowclass1 = args.subheaderrowclass&lt;br /&gt;
	end&lt;br /&gt;
	local subheadernums = getArgNums(&#039;subheader&#039;)&lt;br /&gt;
	for k, num in ipairs(subheadernums) do&lt;br /&gt;
		addRow({&lt;br /&gt;
			data = args[&#039;subheader&#039; .. tostring(num)],&lt;br /&gt;
			datastyle = args.subheaderstyle,&lt;br /&gt;
			rowcellstyle = args[&#039;subheaderstyle&#039; .. tostring(num)],&lt;br /&gt;
			class = args.subheaderclass,&lt;br /&gt;
			rowclass = args[&#039;subheaderrowclass&#039; .. tostring(num)]&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderImages()&lt;br /&gt;
	if args.image then&lt;br /&gt;
		args.image1 = args.image&lt;br /&gt;
	end&lt;br /&gt;
	if args.caption then&lt;br /&gt;
		args.caption1 = args.caption&lt;br /&gt;
	end&lt;br /&gt;
	local imagenums = getArgNums(&#039;image&#039;)&lt;br /&gt;
	for k, num in ipairs(imagenums) do&lt;br /&gt;
		local caption = args[&#039;caption&#039; .. tostring(num)]&lt;br /&gt;
		local data = mw.html.create():wikitext(args[&#039;image&#039; .. tostring(num)])&lt;br /&gt;
		if caption then&lt;br /&gt;
			data&lt;br /&gt;
				:tag(&#039;div&#039;)&lt;br /&gt;
					:cssText(args.captionstyle)&lt;br /&gt;
					:wikitext(caption)&lt;br /&gt;
		end&lt;br /&gt;
		addRow({&lt;br /&gt;
			data = tostring(data),&lt;br /&gt;
			datastyle = args.imagestyle,&lt;br /&gt;
			class = args.imageclass,&lt;br /&gt;
			rowclass = args[&#039;imagerowclass&#039; .. tostring(num)]&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function preprocessRows()&lt;br /&gt;
	-- Gets the union of the header and data argument numbers,&lt;br /&gt;
	-- and renders them all in order using addRow.&lt;br /&gt;
	local rownums = union(getArgNums(&#039;header&#039;), getArgNums(&#039;data&#039;))&lt;br /&gt;
	table.sort(rownums)&lt;br /&gt;
	local lastheader&lt;br /&gt;
	for k, num in ipairs(rownums) do&lt;br /&gt;
		if args[&#039;header&#039; .. tostring(num)] then&lt;br /&gt;
			if lastheader then&lt;br /&gt;
				args[&#039;header&#039; .. tostring(lastheader)] = nil&lt;br /&gt;
			end&lt;br /&gt;
			lastheader = num&lt;br /&gt;
		elseif args[&#039;data&#039; .. tostring(num)] and args[&#039;data&#039; .. tostring(num)]:gsub(&#039;%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]&#039;, &#039;&#039;):match(&#039;^%S&#039;) then&lt;br /&gt;
			local data = args[&#039;data&#039; .. tostring(num)]&lt;br /&gt;
			if data:gsub(&#039;%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]&#039;, &#039;&#039;):match(&#039;%S&#039;) then&lt;br /&gt;
				lastheader = nil&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if lastheader then&lt;br /&gt;
		args[&#039;header&#039; .. tostring(lastheader)] = nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderRows()&lt;br /&gt;
	-- Gets the union of the header and data argument numbers,&lt;br /&gt;
	-- and renders them all in order using addRow.&lt;br /&gt;
	local rownums = union(getArgNums(&#039;header&#039;), getArgNums(&#039;data&#039;))&lt;br /&gt;
	table.sort(rownums)&lt;br /&gt;
	for k, num in ipairs(rownums) do&lt;br /&gt;
		addRow({&lt;br /&gt;
			header = args[&#039;header&#039; .. tostring(num)],&lt;br /&gt;
			label = args[&#039;label&#039; .. tostring(num)],&lt;br /&gt;
			data = args[&#039;data&#039; .. tostring(num)],&lt;br /&gt;
			datastyle = args.datastyle,&lt;br /&gt;
			class = args[&#039;class&#039; .. tostring(num)],&lt;br /&gt;
			rowclass = args[&#039;rowclass&#039; .. tostring(num)],&lt;br /&gt;
			rowstyle = args[&#039;rowstyle&#039; .. tostring(num)],&lt;br /&gt;
			rowcellstyle = args[&#039;rowcellstyle&#039; .. tostring(num)],&lt;br /&gt;
			dataid = args[&#039;dataid&#039; .. tostring(num)],&lt;br /&gt;
			labelid = args[&#039;labelid&#039; .. tostring(num)],&lt;br /&gt;
			headerid = args[&#039;headerid&#039; .. tostring(num)],&lt;br /&gt;
			rowid = args[&#039;rowid&#039; .. tostring(num)]&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderNavBar()&lt;br /&gt;
	if not args.name then return end&lt;br /&gt;
&lt;br /&gt;
	root&lt;br /&gt;
		:tag(&#039;tr&#039;)&lt;br /&gt;
			:tag(&#039;td&#039;)&lt;br /&gt;
				:attr(&#039;colspan&#039;, &#039;2&#039;)&lt;br /&gt;
				:css(&#039;text-align&#039;, &#039;right&#039;)&lt;br /&gt;
				:wikitext(navbar{&lt;br /&gt;
					args.name,&lt;br /&gt;
					mini = 1,&lt;br /&gt;
				})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderItalicTitle()&lt;br /&gt;
	local italicTitle = args[&#039;italic title&#039;] and mw.ustring.lower(args[&#039;italic title&#039;])&lt;br /&gt;
	if italicTitle == &#039;&#039; or italicTitle == &#039;force&#039; or italicTitle == &#039;yes&#039; then&lt;br /&gt;
		root:wikitext(mw.getCurrentFrame():expandTemplate({title = &#039;italic title&#039;}))&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderTrackingCategories()&lt;br /&gt;
	if args.decat ~= &#039;yes&#039; then&lt;br /&gt;
		if args.child == &#039;yes&#039; then&lt;br /&gt;
			if args.title then&lt;br /&gt;
				root:wikitext(&#039;[[Category:Pages which use embedded infobox templates with the title parameter]]&#039;)&lt;br /&gt;
			end&lt;br /&gt;
		elseif #(getArgNums(&#039;data&#039;)) == 0 and mw.title.getCurrentTitle().namespace == 0 then&lt;br /&gt;
			root:wikitext(&#039;[[Category:Articles which use infobox templates with no data rows]]&#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function _infobox()&lt;br /&gt;
	-- Specify the overall layout of the infobox, with special settings&lt;br /&gt;
	-- if the infobox is used as a &#039;child&#039; inside another infobox.&lt;br /&gt;
	if args.child ~= &#039;yes&#039; then&lt;br /&gt;
		root = mw.html.create(&#039;table&#039;)&lt;br /&gt;
&lt;br /&gt;
		root&lt;br /&gt;
			:addClass((args.subbox ~= &#039;yes&#039;) and &#039;infobox&#039; or nil)&lt;br /&gt;
			:addClass(args.bodyclass)&lt;br /&gt;
&lt;br /&gt;
			if args.subbox == &#039;yes&#039; then&lt;br /&gt;
				root&lt;br /&gt;
					:css(&#039;padding&#039;, &#039;0&#039;)&lt;br /&gt;
					:css(&#039;border&#039;, &#039;none&#039;)&lt;br /&gt;
					:css(&#039;margin&#039;, &#039;-3px&#039;)&lt;br /&gt;
					:css(&#039;width&#039;, &#039;auto&#039;)&lt;br /&gt;
					:css(&#039;min-width&#039;, &#039;100%&#039;)&lt;br /&gt;
					:css(&#039;font-size&#039;, &#039;100%&#039;)&lt;br /&gt;
					:css(&#039;clear&#039;, &#039;none&#039;)&lt;br /&gt;
					:css(&#039;float&#039;, &#039;none&#039;)&lt;br /&gt;
					:css(&#039;background-color&#039;, &#039;transparent&#039;)&lt;br /&gt;
			else&lt;br /&gt;
				root&lt;br /&gt;
					:css(&#039;width&#039;, &#039;25em&#039;)&lt;br /&gt;
			end&lt;br /&gt;
		root&lt;br /&gt;
			:cssText(args.bodystyle)&lt;br /&gt;
&lt;br /&gt;
		renderTitle()&lt;br /&gt;
		renderAboveRow()&lt;br /&gt;
	else&lt;br /&gt;
		root = mw.html.create()&lt;br /&gt;
&lt;br /&gt;
		root&lt;br /&gt;
			:wikitext(args.title)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	renderSubheaders()&lt;br /&gt;
	renderImages()&lt;br /&gt;
	if args.autoheaders then&lt;br /&gt;
		preprocessRows()&lt;br /&gt;
	end&lt;br /&gt;
	renderRows()&lt;br /&gt;
	renderBelowRow()&lt;br /&gt;
	renderNavBar()&lt;br /&gt;
	renderItalicTitle()&lt;br /&gt;
	renderTrackingCategories()&lt;br /&gt;
&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function preprocessSingleArg(argName)&lt;br /&gt;
	-- If the argument exists and isn&#039;t blank, add it to the argument table.&lt;br /&gt;
	-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.&lt;br /&gt;
	if origArgs[argName] and origArgs[argName] ~= &#039;&#039; then&lt;br /&gt;
		args[argName] = origArgs[argName]&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function preprocessArgs(prefixTable, step)&lt;br /&gt;
	-- Assign the parameters with the given prefixes to the args table, in order, in batches&lt;br /&gt;
	-- of the step size specified. This is to prevent references etc. from appearing in the&lt;br /&gt;
	-- wrong order. The prefixTable should be an array containing tables, each of which has&lt;br /&gt;
	-- two possible fields, a &amp;quot;prefix&amp;quot; string and a &amp;quot;depend&amp;quot; table. The function always parses&lt;br /&gt;
	-- parameters containing the &amp;quot;prefix&amp;quot; string, but only parses parameters in the &amp;quot;depend&amp;quot;&lt;br /&gt;
	-- table if the prefix parameter is present and non-blank.&lt;br /&gt;
	if type(prefixTable) ~= &#039;table&#039; then&lt;br /&gt;
		error(&amp;quot;Non-table value detected for the prefix table&amp;quot;, 2)&lt;br /&gt;
	end&lt;br /&gt;
	if type(step) ~= &#039;number&#039; then&lt;br /&gt;
		error(&amp;quot;Invalid step value detected&amp;quot;, 2)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Get arguments without a number suffix, and check for bad input.&lt;br /&gt;
	for i,v in ipairs(prefixTable) do&lt;br /&gt;
		if type(v) ~= &#039;table&#039; or type(v.prefix) ~= &amp;quot;string&amp;quot; or (v.depend and type(v.depend) ~= &#039;table&#039;) then&lt;br /&gt;
			error(&#039;Invalid input detected to preprocessArgs prefix table&#039;, 2)&lt;br /&gt;
		end&lt;br /&gt;
		preprocessSingleArg(v.prefix)&lt;br /&gt;
		-- Only parse the depend parameter if the prefix parameter is present and not blank.&lt;br /&gt;
		if args[v.prefix] and v.depend then&lt;br /&gt;
			for j, dependValue in ipairs(v.depend) do&lt;br /&gt;
				if type(dependValue) ~= &#039;string&#039; then&lt;br /&gt;
					error(&#039;Invalid &amp;quot;depend&amp;quot; parameter value detected in preprocessArgs&#039;)&lt;br /&gt;
				end&lt;br /&gt;
				preprocessSingleArg(dependValue)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Get arguments with number suffixes.&lt;br /&gt;
	local a = 1 -- Counter variable.&lt;br /&gt;
	local moreArgumentsExist = true&lt;br /&gt;
	while moreArgumentsExist == true do&lt;br /&gt;
		moreArgumentsExist = false&lt;br /&gt;
		for i = a, a + step - 1 do&lt;br /&gt;
			for j,v in ipairs(prefixTable) do&lt;br /&gt;
				local prefixArgName = v.prefix .. tostring(i)&lt;br /&gt;
				if origArgs[prefixArgName] then&lt;br /&gt;
					moreArgumentsExist = true -- Do another loop if any arguments are found, even blank ones.&lt;br /&gt;
					preprocessSingleArg(prefixArgName)&lt;br /&gt;
				end&lt;br /&gt;
				-- Process the depend table if the prefix argument is present and not blank, or&lt;br /&gt;
				-- we are processing &amp;quot;prefix1&amp;quot; and &amp;quot;prefix&amp;quot; is present and not blank, and&lt;br /&gt;
				-- if the depend table is present.&lt;br /&gt;
				if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then&lt;br /&gt;
					for j,dependValue in ipairs(v.depend) do&lt;br /&gt;
						local dependArgName = dependValue .. tostring(i)&lt;br /&gt;
						preprocessSingleArg(dependArgName)&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		a = a + step&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function parseDataParameters()&lt;br /&gt;
	-- Parse the data parameters in the same order that the old {{infobox}} did, so that&lt;br /&gt;
	-- references etc. will display in the expected places. Parameters that depend on&lt;br /&gt;
	-- another parameter are only processed if that parameter is present, to avoid&lt;br /&gt;
	-- phantom references appearing in article reference lists.&lt;br /&gt;
	preprocessSingleArg(&#039;autoheaders&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;child&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;bodyclass&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;subbox&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;bodystyle&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;title&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;titleclass&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;titlestyle&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;above&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;aboveclass&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;abovestyle&#039;)&lt;br /&gt;
	preprocessArgs({&lt;br /&gt;
		{prefix = &#039;subheader&#039;, depend = {&#039;subheaderstyle&#039;, &#039;subheaderrowclass&#039;}}&lt;br /&gt;
	}, 10)&lt;br /&gt;
	preprocessSingleArg(&#039;subheaderstyle&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;subheaderclass&#039;)&lt;br /&gt;
	preprocessArgs({&lt;br /&gt;
		{prefix = &#039;image&#039;, depend = {&#039;caption&#039;, &#039;imagerowclass&#039;}}&lt;br /&gt;
	}, 10)&lt;br /&gt;
	preprocessSingleArg(&#039;captionstyle&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;imagestyle&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;imageclass&#039;)&lt;br /&gt;
	preprocessArgs({&lt;br /&gt;
		{prefix = &#039;header&#039;},&lt;br /&gt;
		{prefix = &#039;data&#039;, depend = {&#039;label&#039;}},&lt;br /&gt;
		{prefix = &#039;rowclass&#039;},&lt;br /&gt;
		{prefix = &#039;rowstyle&#039;},&lt;br /&gt;
		{prefix = &#039;rowcellstyle&#039;},&lt;br /&gt;
		{prefix = &#039;class&#039;},&lt;br /&gt;
		{prefix = &#039;dataid&#039;},&lt;br /&gt;
		{prefix = &#039;labelid&#039;},&lt;br /&gt;
		{prefix = &#039;headerid&#039;},&lt;br /&gt;
		{prefix = &#039;rowid&#039;}&lt;br /&gt;
	}, 50)&lt;br /&gt;
	preprocessSingleArg(&#039;headerclass&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;headerstyle&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;labelstyle&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;datastyle&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;below&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;belowclass&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;belowstyle&#039;)&lt;br /&gt;
	preprocessSingleArg(&#039;name&#039;)&lt;br /&gt;
	args[&#039;italic title&#039;] = origArgs[&#039;italic title&#039;] -- different behaviour if blank or absent&lt;br /&gt;
	preprocessSingleArg(&#039;decat&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.infobox(frame)&lt;br /&gt;
	-- If called via #invoke, use the args passed into the invoking template.&lt;br /&gt;
	-- Otherwise, for testing purposes, assume args are being passed directly in.&lt;br /&gt;
	if frame == mw.getCurrentFrame() then&lt;br /&gt;
		origArgs = frame:getParent().args&lt;br /&gt;
	else&lt;br /&gt;
		origArgs = frame&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	parseDataParameters()&lt;br /&gt;
	&lt;br /&gt;
	return _infobox()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.infoboxTemplate(frame)&lt;br /&gt;
	-- For calling via #invoke within a template&lt;br /&gt;
	origArgs = {}&lt;br /&gt;
	for k,v in pairs(frame.args) do origArgs[k] = mw.text.trim(v) end&lt;br /&gt;
	&lt;br /&gt;
	parseDataParameters()&lt;br /&gt;
	&lt;br /&gt;
	return _infobox()&lt;br /&gt;
end&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:If_empty&amp;diff=5443</id>
		<title>Módulo:If empty</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:If_empty&amp;diff=5443"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local p = {}&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = require(&#039;Module:Arguments&#039;).getArgs(frame, {wrappers = &#039;Template:If empty&#039;, removeBlanks = false})&lt;br /&gt;
&lt;br /&gt;
	-- For backwards compatibility reasons, the first 8 parameters can be unset instead of being blank,&lt;br /&gt;
	-- even though there&#039;s really no legitimate use case for this. At some point, this will be removed.&lt;br /&gt;
	local lowestNil = math.huge&lt;br /&gt;
	for i = 8,1,-1 do&lt;br /&gt;
		if args[i] == nil then&lt;br /&gt;
			args[i] = &#039;&#039;&lt;br /&gt;
			lowestNil = i&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	for k,v in ipairs(args) do&lt;br /&gt;
		if v ~= &#039;&#039; then&lt;br /&gt;
			if lowestNil &amp;lt; k then&lt;br /&gt;
				-- If any uses of this template depend on the behavior above, add them to a tracking category.&lt;br /&gt;
				-- This is a rather fragile, convoluted, hacky way to do it, but it ensures that this module&#039;s output won&#039;t be modified&lt;br /&gt;
				-- by it.&lt;br /&gt;
				frame:extensionTag(&#039;ref&#039;, &#039;[[Category:Instances of Template:If_empty missing arguments]]&#039;, {group = &#039;TrackingCategory&#039;})&lt;br /&gt;
				frame:extensionTag(&#039;references&#039;, &#039;&#039;, {group = &#039;TrackingCategory&#039;})&lt;br /&gt;
			end&lt;br /&gt;
			return v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:Web_citation&amp;diff=5441</id>
		<title>Plantilla:Web citation</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:Web_citation&amp;diff=5441"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECCIÓN [[Plantilla:Citación web]]&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:Tl&amp;diff=5439</id>
		<title>Plantilla:Tl</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:Tl&amp;diff=5439"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Plantilla:Ep]]&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:PAGENAMEBASE&amp;diff=5437</id>
		<title>Plantilla:PAGENAMEBASE</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:PAGENAMEBASE&amp;diff=5437"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{{{{|safesubst:}}}#Invoke:String|replace|{{{1|{{{{{|safesubst:}}}PAGENAME}}}}}|%s+%b()$||1|false}}&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:LQT_Moved_thread_stub_converted_to_Flow&amp;diff=5435</id>
		<title>Plantilla:LQT Moved thread stub converted to Flow</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:LQT_Moved_thread_stub_converted_to_Flow&amp;diff=5435"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Esta publicación de {{{author}}} se trasladó el {{{date}}}. Puedes encontrarla en [[{{{title}}}]].&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:Infobox&amp;diff=5433</id>
		<title>Plantilla:Infobox</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:Infobox&amp;diff=5433"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:Infobox|infobox}}&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:If_empty&amp;diff=5431</id>
		<title>Plantilla:If empty</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:If_empty&amp;diff=5431"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:If empty|main}}&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:FlowMention&amp;diff=5429</id>
		<title>Plantilla:FlowMention</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:FlowMention&amp;diff=5429"/>
		<updated>2022-11-27T02:41:32Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada: Más plantillas&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;@[[Camarada:{{{1|Example}}}|{{{2|{{{1|Example}}}}}}]]&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Navbar/styles.css&amp;diff=5427</id>
		<title>Módulo:Navbar/styles.css</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Navbar/styles.css&amp;diff=5427"/>
		<updated>2022-11-27T02:38:41Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.navbar {&lt;br /&gt;
	display: inline;&lt;br /&gt;
	font-size: 88%;&lt;br /&gt;
	font-weight: normal;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbar-collapse {&lt;br /&gt;
	float: left;&lt;br /&gt;
	text-align: left;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbar-boxtext {&lt;br /&gt;
	word-spacing: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbar ul {&lt;br /&gt;
	display: inline-block;&lt;br /&gt;
	white-space: nowrap;&lt;br /&gt;
	line-height: inherit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbar-brackets::before {&lt;br /&gt;
	margin-right: -0.125em;&lt;br /&gt;
	content: &#039;[ &#039;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbar-brackets::after {&lt;br /&gt;
	margin-left: -0.125em;&lt;br /&gt;
	content: &#039; ]&#039;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbar li {&lt;br /&gt;
	word-spacing: -0.125em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbar-mini abbr {&lt;br /&gt;
	border-bottom: none;&lt;br /&gt;
	text-decoration: none;&lt;br /&gt;
	cursor: inherit;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbar-ct-full {&lt;br /&gt;
	font-size: 114%;&lt;br /&gt;
	margin: 0 7em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbar-ct-mini {&lt;br /&gt;
	font-size: 114%;&lt;br /&gt;
	margin: 0 4em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Navbar styling when nested in infobox and navbox&lt;br /&gt;
Should consider having a separate TemplateStyles for those specific places&lt;br /&gt;
using an infobox/navbox and a navbar, or possibly override from using template */&lt;br /&gt;
.infobox .navbar {&lt;br /&gt;
	font-size: 100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbox .navbar {&lt;br /&gt;
	display: block;&lt;br /&gt;
	font-size: 100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.navbox-title .navbar {&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	float: left;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	text-align: left;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	margin-right: 0.5em;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Navbar/configuration&amp;diff=5425</id>
		<title>Módulo:Navbar/configuration</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Navbar/configuration&amp;diff=5425"/>
		<updated>2022-11-27T02:38:41Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local configuration = {&lt;br /&gt;
	[&#039;templatestyles&#039;] = &#039;Module:Navbar/styles.css&#039;,&lt;br /&gt;
	[&#039;box_text&#039;] = &#039;This box: &#039;,			-- default text box when not plain or mini&lt;br /&gt;
	[&#039;title_namespace&#039;] = &#039;Template&#039;,		-- namespace to default to for title&lt;br /&gt;
	[&#039;invalid_title&#039;] = &#039;Invalid title &#039;,&lt;br /&gt;
	[&#039;classes&#039;] = { -- set a line to nil if you don&#039;t want it&lt;br /&gt;
		[&#039;navbar&#039;] = &#039;navbar&#039;,&lt;br /&gt;
		[&#039;plainlinks&#039;] = &#039;plainlinks&#039;, -- plainlinks&lt;br /&gt;
		[&#039;horizontal_list&#039;] = &#039;hlist&#039;, -- horizontal list class&lt;br /&gt;
		[&#039;mini&#039;] = &#039;navbar-mini&#039;, -- class indicating small links in the navbar&lt;br /&gt;
		[&#039;this_box&#039;] = &#039;navbar-boxtext&#039;,&lt;br /&gt;
		[&#039;brackets&#039;] = &#039;navbar-brackets&#039;,&lt;br /&gt;
		-- &#039;collapsible&#039; is the key for a class to indicate the navbar is&lt;br /&gt;
		-- setting up the collapsible element in addition to the normal&lt;br /&gt;
		-- navbar.&lt;br /&gt;
		[&#039;collapsible&#039;] = &#039;navbar-collapse&#039;,&lt;br /&gt;
		[&#039;collapsible_title_mini&#039;] = &#039;navbar-ct-mini&#039;,&lt;br /&gt;
		[&#039;collapsible_title_full&#039;] = &#039;navbar-ct-full&#039;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return configuration&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:TableTools&amp;diff=5423</id>
		<title>Módulo:TableTools</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:TableTools&amp;diff=5423"/>
		<updated>2022-11-27T02:38:41Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--                               TableTools                                       --&lt;br /&gt;
--                                                                                --&lt;br /&gt;
-- This module includes a number of functions for dealing with Lua tables.        --&lt;br /&gt;
-- It is a meta-module, meant to be called from other Lua modules, and should     --&lt;br /&gt;
-- not be called directly from #invoke.                                           --&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Define often-used variables and functions.&lt;br /&gt;
local floor = math.floor&lt;br /&gt;
local infinity = math.huge&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local checkTypeMulti = libraryUtil.checkTypeMulti&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isPositiveInteger&lt;br /&gt;
--&lt;br /&gt;
-- This function returns true if the given value is a positive integer, and false&lt;br /&gt;
-- if not. Although it doesn&#039;t operate on tables, it is included here as it is&lt;br /&gt;
-- useful for determining whether a given table key is in the array part or the&lt;br /&gt;
-- hash part of a table.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.isPositiveInteger(v)&lt;br /&gt;
	return type(v) == &#039;number&#039; and v &amp;gt;= 1 and floor(v) == v and v &amp;lt; infinity&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isNan&lt;br /&gt;
--&lt;br /&gt;
-- This function returns true if the given number is a NaN value, and false&lt;br /&gt;
-- if not. Although it doesn&#039;t operate on tables, it is included here as it is&lt;br /&gt;
-- useful for determining whether a value can be a valid table key. Lua will&lt;br /&gt;
-- generate an error if a NaN is used as a table key.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.isNan(v)&lt;br /&gt;
	return type(v) == &#039;number&#039; and tostring(v) == &#039;-nan&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- shallowClone&lt;br /&gt;
--&lt;br /&gt;
-- This returns a clone of a table. The value returned is a new table, but all&lt;br /&gt;
-- subtables and functions are shared. Metamethods are respected, but the returned&lt;br /&gt;
-- table will have no metatable of its own.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.shallowClone(t)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		ret[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- removeDuplicates&lt;br /&gt;
--&lt;br /&gt;
-- This removes duplicate values from an array. Non-positive-integer keys are&lt;br /&gt;
-- ignored. The earliest value is kept, and all subsequent duplicate values are&lt;br /&gt;
-- removed, but otherwise the array order is unchanged.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.removeDuplicates(t)&lt;br /&gt;
	checkType(&#039;removeDuplicates&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local isNan = p.isNan&lt;br /&gt;
	local ret, exists = {}, {}&lt;br /&gt;
	for i, v in ipairs(t) do&lt;br /&gt;
		if isNan(v) then&lt;br /&gt;
			-- NaNs can&#039;t be table keys, and they are also unique, so we don&#039;t need to check existence.&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
		else&lt;br /&gt;
			if not exists[v] then&lt;br /&gt;
				ret[#ret + 1] = v&lt;br /&gt;
				exists[v] = true&lt;br /&gt;
			end&lt;br /&gt;
		end	&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end			&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- numKeys&lt;br /&gt;
--&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of any numerical&lt;br /&gt;
-- keys that have non-nil values, sorted in numerical order.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.numKeys(t)&lt;br /&gt;
	checkType(&#039;numKeys&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local isPositiveInteger = p.isPositiveInteger&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if isPositiveInteger(k) then&lt;br /&gt;
			nums[#nums + 1] = k&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- affixNums&lt;br /&gt;
--&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of keys with the&lt;br /&gt;
-- specified prefix and suffix. For example, for the table&lt;br /&gt;
-- {a1 = &#039;foo&#039;, a3 = &#039;bar&#039;, a6 = &#039;baz&#039;} and the prefix &amp;quot;a&amp;quot;, affixNums will&lt;br /&gt;
-- return {1, 3, 6}.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.affixNums(t, prefix, suffix)&lt;br /&gt;
	checkType(&#039;affixNums&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;affixNums&#039;, 2, prefix, &#039;string&#039;, true)&lt;br /&gt;
	checkType(&#039;affixNums&#039;, 3, suffix, &#039;string&#039;, true)&lt;br /&gt;
&lt;br /&gt;
	local function cleanPattern(s)&lt;br /&gt;
		-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.&lt;br /&gt;
		return s:gsub(&#039;([%(%)%%%.%[%]%*%+%-%?%^%$])&#039;, &#039;%%%1&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	prefix = prefix or &#039;&#039;&lt;br /&gt;
	suffix = suffix or &#039;&#039;&lt;br /&gt;
	prefix = cleanPattern(prefix)&lt;br /&gt;
	suffix = cleanPattern(suffix)&lt;br /&gt;
	local pattern = &#039;^&#039; .. prefix .. &#039;([1-9]%d*)&#039; .. suffix .. &#039;$&#039;&lt;br /&gt;
&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if type(k) == &#039;string&#039; then			&lt;br /&gt;
			local num = mw.ustring.match(k, pattern)&lt;br /&gt;
			if num then&lt;br /&gt;
				nums[#nums + 1] = tonumber(num)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- numData&lt;br /&gt;
--&lt;br /&gt;
-- Given a table with keys like (&amp;quot;foo1&amp;quot;, &amp;quot;bar1&amp;quot;, &amp;quot;foo2&amp;quot;, &amp;quot;baz2&amp;quot;), returns a table&lt;br /&gt;
-- of subtables in the format &lt;br /&gt;
-- { [1] = {foo = &#039;text&#039;, bar = &#039;text&#039;}, [2] = {foo = &#039;text&#039;, baz = &#039;text&#039;} }&lt;br /&gt;
-- Keys that don&#039;t end with an integer are stored in a subtable named &amp;quot;other&amp;quot;.&lt;br /&gt;
-- The compress option compresses the table so that it can be iterated over with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.numData(t, compress)&lt;br /&gt;
	checkType(&#039;numData&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;numData&#039;, 2, compress, &#039;boolean&#039;, true)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		local prefix, num = mw.ustring.match(tostring(k), &#039;^([^0-9]*)([1-9][0-9]*)$&#039;)&lt;br /&gt;
		if num then&lt;br /&gt;
			num = tonumber(num)&lt;br /&gt;
			local subtable = ret[num] or {}&lt;br /&gt;
			if prefix == &#039;&#039; then&lt;br /&gt;
				-- Positional parameters match the blank string; put them at the start of the subtable instead.&lt;br /&gt;
				prefix = 1&lt;br /&gt;
			end&lt;br /&gt;
			subtable[prefix] = v&lt;br /&gt;
			ret[num] = subtable&lt;br /&gt;
		else&lt;br /&gt;
			local subtable = ret.other or {}&lt;br /&gt;
			subtable[k] = v&lt;br /&gt;
			ret.other = subtable&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if compress then&lt;br /&gt;
		local other = ret.other&lt;br /&gt;
		ret = p.compressSparseArray(ret)&lt;br /&gt;
		ret.other = other&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- compressSparseArray&lt;br /&gt;
--&lt;br /&gt;
-- This takes an array with one or more nil values, and removes the nil values&lt;br /&gt;
-- while preserving the order, so that the array can be safely traversed with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.compressSparseArray(t)&lt;br /&gt;
	checkType(&#039;compressSparseArray&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	for _, num in ipairs(nums) do&lt;br /&gt;
		ret[#ret + 1] = t[num]&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- sparseIpairs&lt;br /&gt;
--&lt;br /&gt;
-- This is an iterator for sparse arrays. It can be used like ipairs, but can&lt;br /&gt;
-- handle nil values.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.sparseIpairs(t)&lt;br /&gt;
	checkType(&#039;sparseIpairs&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	local i = 0&lt;br /&gt;
	local lim = #nums&lt;br /&gt;
	return function ()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if i &amp;lt;= lim then&lt;br /&gt;
			local key = nums[i]&lt;br /&gt;
			return key, t[key]&lt;br /&gt;
		else&lt;br /&gt;
			return nil, nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- size&lt;br /&gt;
--&lt;br /&gt;
-- This returns the size of a key/value pair table. It will also work on arrays,&lt;br /&gt;
-- but for arrays it is more efficient to use the # operator.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
function p.size(t)&lt;br /&gt;
	checkType(&#039;size&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for k in pairs(t) do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return i&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function defaultKeySort(item1, item2)&lt;br /&gt;
	-- &amp;quot;number&amp;quot; &amp;lt; &amp;quot;string&amp;quot;, so numbers will be sorted before strings.&lt;br /&gt;
	local type1, type2 = type(item1), type(item2)&lt;br /&gt;
	if type1 ~= type2 then&lt;br /&gt;
		return type1 &amp;lt; type2&lt;br /&gt;
	else -- This will fail with table, boolean, function.&lt;br /&gt;
		return item1 &amp;lt; item2&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
	Returns a list of the keys in a table, sorted using either a default&lt;br /&gt;
	comparison function or a custom keySort function.&lt;br /&gt;
]]&lt;br /&gt;
function p.keysToList(t, keySort, checked)&lt;br /&gt;
	if not checked then&lt;br /&gt;
		checkType(&#039;keysToList&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
		checkTypeMulti(&#039;keysToList&#039;, 2, keySort, { &#039;function&#039;, &#039;boolean&#039;, &#039;nil&#039; })&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local list = {}&lt;br /&gt;
	local index = 1&lt;br /&gt;
	for key, value in pairs(t) do&lt;br /&gt;
		list[index] = key&lt;br /&gt;
		index = index + 1&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if keySort ~= false then&lt;br /&gt;
		keySort = type(keySort) == &#039;function&#039; and keySort or defaultKeySort&lt;br /&gt;
		&lt;br /&gt;
		table.sort(list, keySort)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return list&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
	Iterates through a table, with the keys sorted using the keysToList function.&lt;br /&gt;
	If there are only numerical keys, sparseIpairs is probably more efficient.&lt;br /&gt;
]]&lt;br /&gt;
function p.sortedPairs(t, keySort)&lt;br /&gt;
	checkType(&#039;sortedPairs&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;sortedPairs&#039;, 2, keySort, &#039;function&#039;, true)&lt;br /&gt;
	&lt;br /&gt;
	local list = p.keysToList(t, keySort, true)&lt;br /&gt;
	&lt;br /&gt;
	local i = 0&lt;br /&gt;
	return function()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		local key = list[i]&lt;br /&gt;
		if key ~= nil then&lt;br /&gt;
			return key, t[key]&lt;br /&gt;
		else&lt;br /&gt;
			return nil, nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
	Returns true if all keys in the table are consecutive integers starting at 1.&lt;br /&gt;
--]]&lt;br /&gt;
function p.isArray(t)&lt;br /&gt;
	checkType(&amp;quot;isArray&amp;quot;, 1, t, &amp;quot;table&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if t[i] == nil then&lt;br /&gt;
			return false&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- { &amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot; } -&amp;gt; { a = 1, b = 2, c = 3 }&lt;br /&gt;
function p.invert(array)&lt;br /&gt;
	checkType(&amp;quot;invert&amp;quot;, 1, array, &amp;quot;table&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	local map = {}&lt;br /&gt;
	for i, v in ipairs(array) do&lt;br /&gt;
		map[v] = i&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return map&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
	{ &amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot; } -&amp;gt; { [&amp;quot;a&amp;quot;] = true, [&amp;quot;b&amp;quot;] = true, [&amp;quot;c&amp;quot;] = true }&lt;br /&gt;
--]]&lt;br /&gt;
function p.listToSet(t)&lt;br /&gt;
	checkType(&amp;quot;listToSet&amp;quot;, 1, t, &amp;quot;table&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	local set = {}&lt;br /&gt;
	for _, item in ipairs(t) do&lt;br /&gt;
		set[item] = true&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return set&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
	Recursive deep copy function.&lt;br /&gt;
	Preserves identities of subtables.&lt;br /&gt;
	&lt;br /&gt;
]]&lt;br /&gt;
local function _deepCopy(orig, includeMetatable, already_seen)&lt;br /&gt;
	-- Stores copies of tables indexed by the original table.&lt;br /&gt;
	already_seen = already_seen or {}&lt;br /&gt;
	&lt;br /&gt;
	local copy = already_seen[orig]&lt;br /&gt;
	if copy ~= nil then&lt;br /&gt;
		return copy&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if type(orig) == &#039;table&#039; then&lt;br /&gt;
		copy = {}&lt;br /&gt;
		for orig_key, orig_value in pairs(orig) do&lt;br /&gt;
			copy[deepcopy(orig_key, includeMetatable, already_seen)] = deepcopy(orig_value, includeMetatable, already_seen)&lt;br /&gt;
		end&lt;br /&gt;
		already_seen[orig] = copy&lt;br /&gt;
		&lt;br /&gt;
		if includeMetatable then&lt;br /&gt;
			local mt = getmetatable(orig)&lt;br /&gt;
			if mt ~= nil then&lt;br /&gt;
				local mt_copy = deepcopy(mt, includeMetatable, already_seen)&lt;br /&gt;
				setmetatable(copy, mt_copy)&lt;br /&gt;
				already_seen[mt] = mt_copy&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else -- number, string, boolean, etc&lt;br /&gt;
		copy = orig&lt;br /&gt;
	end&lt;br /&gt;
	return copy&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.deepCopy(orig, noMetatable, already_seen)&lt;br /&gt;
	checkType(&amp;quot;deepCopy&amp;quot;, 3, already_seen, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
	&lt;br /&gt;
	return _deepCopy(orig, not noMetatable, already_seen)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
	Concatenates all values in the table that are indexed by a number, in order.&lt;br /&gt;
	sparseConcat{ a, nil, c, d }  =&amp;gt;  &amp;quot;acd&amp;quot;&lt;br /&gt;
	sparseConcat{ nil, b, c, d }  =&amp;gt;  &amp;quot;bcd&amp;quot;&lt;br /&gt;
]]&lt;br /&gt;
function p.sparseConcat(t, sep, i, j)&lt;br /&gt;
	local list = {}&lt;br /&gt;
	&lt;br /&gt;
	local list_i = 0&lt;br /&gt;
	for _, v in p.sparseIpairs(t) do&lt;br /&gt;
		list_i = list_i + 1&lt;br /&gt;
		list[list_i] = v&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return table.concat(list, sep, i, j)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Finds the length of an array, or of a quasi-array with keys such&lt;br /&gt;
-- as &amp;quot;data1&amp;quot;, &amp;quot;data2&amp;quot;, etc., using an exponential search algorithm. &lt;br /&gt;
-- It is similar to the operator #, but may return&lt;br /&gt;
-- a different value when there are gaps in the array portion of the table.&lt;br /&gt;
-- Intended to be used on data loaded with mw.loadData. For other tables, use #.&lt;br /&gt;
-- Note: #frame.args in frame object always be set to 0, regardless of &lt;br /&gt;
-- the number of unnamed template parameters, so use this function for&lt;br /&gt;
-- frame.args.&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
function p.length(t, prefix)&lt;br /&gt;
	-- requiring module inline so that [[Module:Exponential search]]&lt;br /&gt;
	-- which is only needed by this one function&lt;br /&gt;
	-- doesn&#039;t get millions of transclusions&lt;br /&gt;
	local expSearch = require(&amp;quot;Module:Exponential search&amp;quot;)&lt;br /&gt;
	checkType(&#039;length&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;length&#039;, 2, prefix, &#039;string&#039;, true)&lt;br /&gt;
	return expSearch(function(i)&lt;br /&gt;
		local key&lt;br /&gt;
		if prefix then&lt;br /&gt;
			key = prefix .. tostring(i)&lt;br /&gt;
		else&lt;br /&gt;
			key = i&lt;br /&gt;
		end&lt;br /&gt;
		return t[key] ~= nil&lt;br /&gt;
	end) or 0&lt;br /&gt;
end&lt;br /&gt;
function p.inArray(arr, valueToFind)&lt;br /&gt;
	checkType(&amp;quot;inArray&amp;quot;, 1, arr, &amp;quot;table&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	-- if valueToFind is nil, error?&lt;br /&gt;
	&lt;br /&gt;
	for _, v in ipairs(arr) do&lt;br /&gt;
		if v == valueToFind then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Separated_entries&amp;diff=5421</id>
		<title>Módulo:Separated entries</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Separated_entries&amp;diff=5421"/>
		<updated>2022-11-27T02:38:41Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module takes positional parameters as input and concatenates them with&lt;br /&gt;
-- an optional separator. The final separator (the &amp;quot;conjunction&amp;quot;) can be&lt;br /&gt;
-- specified independently, enabling natural-language lists like&lt;br /&gt;
-- &amp;quot;foo, bar, baz and qux&amp;quot;. The starting parameter can also be specified.&lt;br /&gt;
&lt;br /&gt;
local compressSparseArray = require(&#039;Module:TableTools&#039;).compressSparseArray&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
	local separator = args.separator&lt;br /&gt;
		-- Decode (convert to Unicode) HTML escape sequences, such as &amp;quot;&amp;amp;#32;&amp;quot; for space.&lt;br /&gt;
		and mw.text.decode(args.separator) or &#039;&#039;&lt;br /&gt;
	local conjunction = args.conjunction and mw.text.decode(args.conjunction) or separator&lt;br /&gt;
	-- Discard values before the starting parameter.&lt;br /&gt;
	local start = tonumber(args.start)&lt;br /&gt;
	if start then&lt;br /&gt;
		for i = 1, start - 1 do args[i] = nil end&lt;br /&gt;
	end&lt;br /&gt;
	-- Discard named parameters.&lt;br /&gt;
	local values = compressSparseArray(args)&lt;br /&gt;
	return mw.text.listToText(values, separator, conjunction)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeInvokeFunction(separator, conjunction, first)&lt;br /&gt;
	return function (frame)&lt;br /&gt;
		local args = require(&#039;Module:Arguments&#039;).getArgs(frame)&lt;br /&gt;
		args.separator = separator or args.separator&lt;br /&gt;
		args.conjunction = conjunction or args.conjunction&lt;br /&gt;
		args.first = first or args.first&lt;br /&gt;
		return p._main(args)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.main = makeInvokeFunction()&lt;br /&gt;
p.br = makeInvokeFunction(&#039;&amp;lt;br /&amp;gt;&#039;)&lt;br /&gt;
p.comma = makeInvokeFunction(mw.message.new(&#039;comma-separator&#039;):plain())&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Arguments&amp;diff=5419</id>
		<title>Módulo:Arguments</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Arguments&amp;diff=5419"/>
		<updated>2022-11-27T02:38:41Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module provides easy processing of arguments passed to Scribunto from&lt;br /&gt;
-- #invoke. It is intended for use by other Lua modules, and should not be&lt;br /&gt;
-- called from #invoke directly.&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
&lt;br /&gt;
local arguments = {}&lt;br /&gt;
&lt;br /&gt;
-- Generate four different tidyVal functions, so that we don&#039;t have to check the&lt;br /&gt;
-- options every time we call it.&lt;br /&gt;
&lt;br /&gt;
local function tidyValDefault(key, val)&lt;br /&gt;
	if type(val) == &#039;string&#039; then&lt;br /&gt;
		val = val:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
		if val == &#039;&#039; then&lt;br /&gt;
			return nil&lt;br /&gt;
		else&lt;br /&gt;
			return val&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return val&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function tidyValTrimOnly(key, val)&lt;br /&gt;
	if type(val) == &#039;string&#039; then&lt;br /&gt;
		return val:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		return val&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function tidyValRemoveBlanksOnly(key, val)&lt;br /&gt;
	if type(val) == &#039;string&#039; then&lt;br /&gt;
		if val:find(&#039;%S&#039;) then&lt;br /&gt;
			return val&lt;br /&gt;
		else&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return val&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function tidyValNoChange(key, val)&lt;br /&gt;
	return val&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function matchesTitle(given, title)&lt;br /&gt;
	local tp = type( given )&lt;br /&gt;
	return (tp == &#039;string&#039; or tp == &#039;number&#039;) and mw.title.new( given ).prefixedText == title&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local translate_mt = { __index = function(t, k) return k end }&lt;br /&gt;
&lt;br /&gt;
function arguments.getArgs(frame, options)&lt;br /&gt;
	checkType(&#039;getArgs&#039;, 1, frame, &#039;table&#039;, true)&lt;br /&gt;
	checkType(&#039;getArgs&#039;, 2, options, &#039;table&#039;, true)&lt;br /&gt;
	frame = frame or {}&lt;br /&gt;
	options = options or {}&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Set up argument translation.&lt;br /&gt;
	--]]&lt;br /&gt;
	options.translate = options.translate or {}&lt;br /&gt;
	if getmetatable(options.translate) == nil then&lt;br /&gt;
		setmetatable(options.translate, translate_mt)&lt;br /&gt;
	end&lt;br /&gt;
	if options.backtranslate == nil then&lt;br /&gt;
		options.backtranslate = {}&lt;br /&gt;
		for k,v in pairs(options.translate) do&lt;br /&gt;
			options.backtranslate[v] = k&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if options.backtranslate and getmetatable(options.backtranslate) == nil then&lt;br /&gt;
		setmetatable(options.backtranslate, {&lt;br /&gt;
			__index = function(t, k)&lt;br /&gt;
				if options.translate[k] ~= k then&lt;br /&gt;
					return nil&lt;br /&gt;
				else&lt;br /&gt;
					return k&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Get the argument tables. If we were passed a valid frame object, get the&lt;br /&gt;
	-- frame arguments (fargs) and the parent frame arguments (pargs), depending&lt;br /&gt;
	-- on the options set and on the parent frame&#039;s availability. If we weren&#039;t&lt;br /&gt;
	-- passed a valid frame object, we are being called from another Lua module&lt;br /&gt;
	-- or from the debug console, so assume that we were passed a table of args&lt;br /&gt;
	-- directly, and assign it to a new variable (luaArgs).&lt;br /&gt;
	--]]&lt;br /&gt;
	local fargs, pargs, luaArgs&lt;br /&gt;
	if type(frame.args) == &#039;table&#039; and type(frame.getParent) == &#039;function&#039; then&lt;br /&gt;
		if options.wrappers then&lt;br /&gt;
			--[[&lt;br /&gt;
			-- The wrappers option makes Module:Arguments look up arguments in&lt;br /&gt;
			-- either the frame argument table or the parent argument table, but&lt;br /&gt;
			-- not both. This means that users can use either the #invoke syntax&lt;br /&gt;
			-- or a wrapper template without the loss of performance associated&lt;br /&gt;
			-- with looking arguments up in both the frame and the parent frame.&lt;br /&gt;
			-- Module:Arguments will look up arguments in the parent frame&lt;br /&gt;
			-- if it finds the parent frame&#039;s title in options.wrapper;&lt;br /&gt;
			-- otherwise it will look up arguments in the frame object passed&lt;br /&gt;
			-- to getArgs.&lt;br /&gt;
			--]]&lt;br /&gt;
			local parent = frame:getParent()&lt;br /&gt;
			if not parent then&lt;br /&gt;
				fargs = frame.args&lt;br /&gt;
			else&lt;br /&gt;
				local title = parent:getTitle():gsub(&#039;/sandbox$&#039;, &#039;&#039;)&lt;br /&gt;
				local found = false&lt;br /&gt;
				if matchesTitle(options.wrappers, title) then&lt;br /&gt;
					found = true&lt;br /&gt;
				elseif type(options.wrappers) == &#039;table&#039; then&lt;br /&gt;
					for _,v in pairs(options.wrappers) do&lt;br /&gt;
						if matchesTitle(v, title) then&lt;br /&gt;
							found = true&lt;br /&gt;
							break&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
&lt;br /&gt;
				-- We test for false specifically here so that nil (the default) acts like true.&lt;br /&gt;
				if found or options.frameOnly == false then&lt;br /&gt;
					pargs = parent.args&lt;br /&gt;
				end&lt;br /&gt;
				if not found or options.parentOnly == false then&lt;br /&gt;
					fargs = frame.args&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- options.wrapper isn&#039;t set, so check the other options.&lt;br /&gt;
			if not options.parentOnly then&lt;br /&gt;
				fargs = frame.args&lt;br /&gt;
			end&lt;br /&gt;
			if not options.frameOnly then&lt;br /&gt;
				local parent = frame:getParent()&lt;br /&gt;
				pargs = parent and parent.args or nil&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if options.parentFirst then&lt;br /&gt;
			fargs, pargs = pargs, fargs&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		luaArgs = frame&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set the order of precedence of the argument tables. If the variables are&lt;br /&gt;
	-- nil, nothing will be added to the table, which is how we avoid clashes&lt;br /&gt;
	-- between the frame/parent args and the Lua args.&lt;br /&gt;
	local argTables = {fargs}&lt;br /&gt;
	argTables[#argTables + 1] = pargs&lt;br /&gt;
	argTables[#argTables + 1] = luaArgs&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Generate the tidyVal function. If it has been specified by the user, we&lt;br /&gt;
	-- use that; if not, we choose one of four functions depending on the&lt;br /&gt;
	-- options chosen. This is so that we don&#039;t have to call the options table&lt;br /&gt;
	-- every time the function is called.&lt;br /&gt;
	--]]&lt;br /&gt;
	local tidyVal = options.valueFunc&lt;br /&gt;
	if tidyVal then&lt;br /&gt;
		if type(tidyVal) ~= &#039;function&#039; then&lt;br /&gt;
			error(&lt;br /&gt;
				&amp;quot;bad value assigned to option &#039;valueFunc&#039;&amp;quot;&lt;br /&gt;
					.. &#039;(function expected, got &#039;&lt;br /&gt;
					.. type(tidyVal)&lt;br /&gt;
					.. &#039;)&#039;,&lt;br /&gt;
				2&lt;br /&gt;
			)&lt;br /&gt;
		end&lt;br /&gt;
	elseif options.trim ~= false then&lt;br /&gt;
		if options.removeBlanks ~= false then&lt;br /&gt;
			tidyVal = tidyValDefault&lt;br /&gt;
		else&lt;br /&gt;
			tidyVal = tidyValTrimOnly&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		if options.removeBlanks ~= false then&lt;br /&gt;
			tidyVal = tidyValRemoveBlanksOnly&lt;br /&gt;
		else&lt;br /&gt;
			tidyVal = tidyValNoChange&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Set up the args, metaArgs and nilArgs tables. args will be the one&lt;br /&gt;
	-- accessed from functions, and metaArgs will hold the actual arguments. Nil&lt;br /&gt;
	-- arguments are memoized in nilArgs, and the metatable connects all of them&lt;br /&gt;
	-- together.&lt;br /&gt;
	--]]&lt;br /&gt;
	local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}&lt;br /&gt;
	setmetatable(args, metatable)&lt;br /&gt;
&lt;br /&gt;
	local function mergeArgs(tables)&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Accepts multiple tables as input and merges their keys and values&lt;br /&gt;
		-- into one table. If a value is already present it is not overwritten;&lt;br /&gt;
		-- tables listed earlier have precedence. We are also memoizing nil&lt;br /&gt;
		-- values, which can be overwritten if they are &#039;s&#039; (soft).&lt;br /&gt;
		--]]&lt;br /&gt;
		for _, t in ipairs(tables) do&lt;br /&gt;
			for key, val in pairs(t) do&lt;br /&gt;
				if metaArgs[key] == nil and nilArgs[key] ~= &#039;h&#039; then&lt;br /&gt;
					local tidiedVal = tidyVal(key, val)&lt;br /&gt;
					if tidiedVal == nil then&lt;br /&gt;
						nilArgs[key] = &#039;s&#039;&lt;br /&gt;
					else&lt;br /&gt;
						metaArgs[key] = tidiedVal&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Define metatable behaviour. Arguments are memoized in the metaArgs table,&lt;br /&gt;
	-- and are only fetched from the argument tables once. Fetching arguments&lt;br /&gt;
	-- from the argument tables is the most resource-intensive step in this&lt;br /&gt;
	-- module, so we try and avoid it where possible. For this reason, nil&lt;br /&gt;
	-- arguments are also memoized, in the nilArgs table. Also, we keep a record&lt;br /&gt;
	-- in the metatable of when pairs and ipairs have been called, so we do not&lt;br /&gt;
	-- run pairs and ipairs on the argument tables more than once. We also do&lt;br /&gt;
	-- not run ipairs on fargs and pargs if pairs has already been run, as all&lt;br /&gt;
	-- the arguments will already have been copied over.&lt;br /&gt;
	--]]&lt;br /&gt;
&lt;br /&gt;
	metatable.__index = function (t, key)&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Fetches an argument when the args table is indexed. First we check&lt;br /&gt;
		-- to see if the value is memoized, and if not we try and fetch it from&lt;br /&gt;
		-- the argument tables. When we check memoization, we need to check&lt;br /&gt;
		-- metaArgs before nilArgs, as both can be non-nil at the same time.&lt;br /&gt;
		-- If the argument is not present in metaArgs, we also check whether&lt;br /&gt;
		-- pairs has been run yet. If pairs has already been run, we return nil.&lt;br /&gt;
		-- This is because all the arguments will have already been copied into&lt;br /&gt;
		-- metaArgs by the mergeArgs function, meaning that any other arguments&lt;br /&gt;
		-- must be nil.&lt;br /&gt;
		--]]&lt;br /&gt;
		if type(key) == &#039;string&#039; then&lt;br /&gt;
			key = options.translate[key]&lt;br /&gt;
		end&lt;br /&gt;
		local val = metaArgs[key]&lt;br /&gt;
		if val ~= nil then&lt;br /&gt;
			return val&lt;br /&gt;
		elseif metatable.donePairs or nilArgs[key] then&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
		for _, argTable in ipairs(argTables) do&lt;br /&gt;
			local argTableVal = tidyVal(key, argTable[key])&lt;br /&gt;
			if argTableVal ~= nil then&lt;br /&gt;
				metaArgs[key] = argTableVal&lt;br /&gt;
				return argTableVal&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		nilArgs[key] = &#039;h&#039;&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	metatable.__newindex = function (t, key, val)&lt;br /&gt;
		-- This function is called when a module tries to add a new value to the&lt;br /&gt;
		-- args table, or tries to change an existing value.&lt;br /&gt;
		if type(key) == &#039;string&#039; then&lt;br /&gt;
			key = options.translate[key]&lt;br /&gt;
		end&lt;br /&gt;
		if options.readOnly then&lt;br /&gt;
			error(&lt;br /&gt;
				&#039;could not write to argument table key &amp;quot;&#039;&lt;br /&gt;
					.. tostring(key)&lt;br /&gt;
					.. &#039;&amp;quot;; the table is read-only&#039;,&lt;br /&gt;
				2&lt;br /&gt;
			)&lt;br /&gt;
		elseif options.noOverwrite and args[key] ~= nil then&lt;br /&gt;
			error(&lt;br /&gt;
				&#039;could not write to argument table key &amp;quot;&#039;&lt;br /&gt;
					.. tostring(key)&lt;br /&gt;
					.. &#039;&amp;quot;; overwriting existing arguments is not permitted&#039;,&lt;br /&gt;
				2&lt;br /&gt;
			)&lt;br /&gt;
		elseif val == nil then&lt;br /&gt;
			--[[&lt;br /&gt;
			-- If the argument is to be overwritten with nil, we need to erase&lt;br /&gt;
			-- the value in metaArgs, so that __index, __pairs and __ipairs do&lt;br /&gt;
			-- not use a previous existing value, if present; and we also need&lt;br /&gt;
			-- to memoize the nil in nilArgs, so that the value isn&#039;t looked&lt;br /&gt;
			-- up in the argument tables if it is accessed again.&lt;br /&gt;
			--]]&lt;br /&gt;
			metaArgs[key] = nil&lt;br /&gt;
			nilArgs[key] = &#039;h&#039;&lt;br /&gt;
		else&lt;br /&gt;
			metaArgs[key] = val&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function translatenext(invariant)&lt;br /&gt;
		local k, v = next(invariant.t, invariant.k)&lt;br /&gt;
		invariant.k = k&lt;br /&gt;
		if k == nil then&lt;br /&gt;
			return nil&lt;br /&gt;
		elseif type(k) ~= &#039;string&#039; or not options.backtranslate then&lt;br /&gt;
			return k, v&lt;br /&gt;
		else&lt;br /&gt;
			local backtranslate = options.backtranslate[k]&lt;br /&gt;
			if backtranslate == nil then&lt;br /&gt;
				-- Skip this one. This is a tail call, so this won&#039;t cause stack overflow&lt;br /&gt;
				return translatenext(invariant)&lt;br /&gt;
			else&lt;br /&gt;
				return backtranslate, v&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	metatable.__pairs = function ()&lt;br /&gt;
		-- Called when pairs is run on the args table.&lt;br /&gt;
		if not metatable.donePairs then&lt;br /&gt;
			mergeArgs(argTables)&lt;br /&gt;
			metatable.donePairs = true&lt;br /&gt;
		end&lt;br /&gt;
		return translatenext, { t = metaArgs }&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function inext(t, i)&lt;br /&gt;
		-- This uses our __index metamethod&lt;br /&gt;
		local v = t[i + 1]&lt;br /&gt;
		if v ~= nil then&lt;br /&gt;
			return i + 1, v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	metatable.__ipairs = function (t)&lt;br /&gt;
		-- Called when ipairs is run on the args table.&lt;br /&gt;
		return inext, t, 0&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return args&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return arguments&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Date&amp;diff=5417</id>
		<title>Módulo:Date</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=M%C3%B3dulo:Date&amp;diff=5417"/>
		<updated>2022-11-27T02:38:40Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Date functions for use by other modules.&lt;br /&gt;
-- I18N and time zones are not supported.&lt;br /&gt;
&lt;br /&gt;
local MINUS = &#039;−&#039;  -- Unicode U+2212 MINUS SIGN&lt;br /&gt;
local floor = math.floor&lt;br /&gt;
&lt;br /&gt;
local Date, DateDiff, diffmt  -- forward declarations&lt;br /&gt;
local uniq = { &#039;unique identifier&#039; }&lt;br /&gt;
&lt;br /&gt;
local function is_date(t)&lt;br /&gt;
	-- The system used to make a date read-only means there is no unique&lt;br /&gt;
	-- metatable that is conveniently accessible to check.&lt;br /&gt;
	return type(t) == &#039;table&#039; and t._id == uniq&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function is_diff(t)&lt;br /&gt;
	return type(t) == &#039;table&#039; and getmetatable(t) == diffmt&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function _list_join(list, sep)&lt;br /&gt;
	return table.concat(list, sep)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function collection()&lt;br /&gt;
	-- Return a table to hold items.&lt;br /&gt;
	return {&lt;br /&gt;
		n = 0,&lt;br /&gt;
		add = function (self, item)&lt;br /&gt;
			self.n = self.n + 1&lt;br /&gt;
			self[self.n] = item&lt;br /&gt;
		end,&lt;br /&gt;
		join = _list_join,&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function strip_to_nil(text)&lt;br /&gt;
	-- If text is a string, return its trimmed content, or nil if empty.&lt;br /&gt;
	-- Otherwise return text (convenient when Date fields are provided from&lt;br /&gt;
	-- another module which may pass a string, a number, or another type).&lt;br /&gt;
	if type(text) == &#039;string&#039; then&lt;br /&gt;
		text = text:match(&#039;(%S.-)%s*$&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	return text&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function is_leap_year(year, calname)&lt;br /&gt;
	-- Return true if year is a leap year.&lt;br /&gt;
	if calname == &#039;Julian&#039; then&lt;br /&gt;
		return year % 4 == 0&lt;br /&gt;
	end&lt;br /&gt;
	return (year % 4 == 0 and year % 100 ~= 0) or year % 400 == 0&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function days_in_month(year, month, calname)&lt;br /&gt;
	-- Return number of days (1..31) in given month (1..12).&lt;br /&gt;
	if month == 2 and is_leap_year(year, calname) then&lt;br /&gt;
		return 29&lt;br /&gt;
	end&lt;br /&gt;
	return ({ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 })[month]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function h_m_s(time)&lt;br /&gt;
	-- Return hour, minute, second extracted from fraction of a day.&lt;br /&gt;
	time = floor(time * 24 * 3600 + 0.5)  -- number of seconds&lt;br /&gt;
	local second = time % 60&lt;br /&gt;
	time = floor(time / 60)&lt;br /&gt;
	return floor(time / 60), time % 60, second&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function hms(date)&lt;br /&gt;
	-- Return fraction of a day from date&#039;s time, where (0 &amp;lt;= fraction &amp;lt; 1)&lt;br /&gt;
	-- if the values are valid, but could be anything if outside range.&lt;br /&gt;
	return (date.hour + (date.minute + date.second / 60) / 60) / 24&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function julian_date(date)&lt;br /&gt;
	-- Return jd, jdz from a Julian or Gregorian calendar date where&lt;br /&gt;
	--   jd = Julian date and its fractional part is zero at noon&lt;br /&gt;
	--   jdz = same, but assume time is 00:00:00 if no time given&lt;br /&gt;
	-- http://www.tondering.dk/claus/cal/julperiod.php#formula&lt;br /&gt;
	-- Testing shows this works for all dates from year -9999 to 9999!&lt;br /&gt;
	-- JDN 0 is the 24-hour period starting at noon UTC on Monday&lt;br /&gt;
	--    1 January 4713 BC  = (-4712, 1, 1)   Julian calendar&lt;br /&gt;
	--   24 November 4714 BC = (-4713, 11, 24) Gregorian calendar&lt;br /&gt;
	local offset&lt;br /&gt;
	local a = floor((14 - date.month)/12)&lt;br /&gt;
	local y = date.year + 4800 - a&lt;br /&gt;
	if date.calendar == &#039;Julian&#039; then&lt;br /&gt;
		offset = floor(y/4) - 32083&lt;br /&gt;
	else&lt;br /&gt;
		offset = floor(y/4) - floor(y/100) + floor(y/400) - 32045&lt;br /&gt;
	end&lt;br /&gt;
	local m = date.month + 12*a - 3&lt;br /&gt;
	local jd = date.day + floor((153*m + 2)/5) + 365*y + offset&lt;br /&gt;
	if date.hastime then&lt;br /&gt;
		jd = jd + hms(date) - 0.5&lt;br /&gt;
		return jd, jd&lt;br /&gt;
	end&lt;br /&gt;
	return jd, jd - 0.5&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function set_date_from_jd(date)&lt;br /&gt;
	-- Set the fields of table date from its Julian date field.&lt;br /&gt;
	-- Return true if date is valid.&lt;br /&gt;
	-- http://www.tondering.dk/claus/cal/julperiod.php#formula&lt;br /&gt;
	-- This handles the proleptic Julian and Gregorian calendars.&lt;br /&gt;
	-- Negative Julian dates are not defined but they work.&lt;br /&gt;
	local calname = date.calendar&lt;br /&gt;
	local low, high  -- min/max limits for date ranges −9999-01-01 to 9999-12-31&lt;br /&gt;
	if calname == &#039;Gregorian&#039; then&lt;br /&gt;
		low, high = -1930999.5, 5373484.49999&lt;br /&gt;
	elseif calname == &#039;Julian&#039; then&lt;br /&gt;
		low, high = -1931076.5, 5373557.49999&lt;br /&gt;
	else&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	local jd = date.jd&lt;br /&gt;
	if not (type(jd) == &#039;number&#039; and low &amp;lt;= jd and jd &amp;lt;= high) then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	local jdn = floor(jd)&lt;br /&gt;
	if date.hastime then&lt;br /&gt;
		local time = jd - jdn  -- 0 &amp;lt;= time &amp;lt; 1&lt;br /&gt;
		if time &amp;gt;= 0.5 then    -- if at or after midnight of next day&lt;br /&gt;
			jdn = jdn + 1&lt;br /&gt;
			time = time - 0.5&lt;br /&gt;
		else&lt;br /&gt;
			time = time + 0.5&lt;br /&gt;
		end&lt;br /&gt;
		date.hour, date.minute, date.second = h_m_s(time)&lt;br /&gt;
	else&lt;br /&gt;
		date.second = 0&lt;br /&gt;
		date.minute = 0&lt;br /&gt;
		date.hour = 0&lt;br /&gt;
	end&lt;br /&gt;
	local b, c&lt;br /&gt;
	if calname == &#039;Julian&#039; then&lt;br /&gt;
		b = 0&lt;br /&gt;
		c = jdn + 32082&lt;br /&gt;
	else  -- Gregorian&lt;br /&gt;
		local a = jdn + 32044&lt;br /&gt;
		b = floor((4*a + 3)/146097)&lt;br /&gt;
		c = a - floor(146097*b/4)&lt;br /&gt;
	end&lt;br /&gt;
	local d = floor((4*c + 3)/1461)&lt;br /&gt;
	local e = c - floor(1461*d/4)&lt;br /&gt;
	local m = floor((5*e + 2)/153)&lt;br /&gt;
	date.day = e - floor((153*m + 2)/5) + 1&lt;br /&gt;
	date.month = m + 3 - 12*floor(m/10)&lt;br /&gt;
	date.year = 100*b + d - 4800 + floor(m/10)&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function fix_numbers(numbers, y, m, d, H, M, S, partial, hastime, calendar)&lt;br /&gt;
	-- Put the result of normalizing the given values in table numbers.&lt;br /&gt;
	-- The result will have valid m, d values if y is valid; caller checks y.&lt;br /&gt;
	-- The logic of PHP mktime is followed where m or d can be zero to mean&lt;br /&gt;
	-- the previous unit, and -1 is the one before that, etc.&lt;br /&gt;
	-- Positive values carry forward.&lt;br /&gt;
	local date&lt;br /&gt;
	if not (1 &amp;lt;= m and m &amp;lt;= 12) then&lt;br /&gt;
		date = Date(y, 1, 1)&lt;br /&gt;
		if not date then return end&lt;br /&gt;
		date = date + ((m - 1) .. &#039;m&#039;)&lt;br /&gt;
		y, m = date.year, date.month&lt;br /&gt;
	end&lt;br /&gt;
	local days_hms&lt;br /&gt;
	if not partial then&lt;br /&gt;
		if hastime and H and M and S then&lt;br /&gt;
			if not (0 &amp;lt;= H and H &amp;lt;= 23 and&lt;br /&gt;
					0 &amp;lt;= M and M &amp;lt;= 59 and&lt;br /&gt;
					0 &amp;lt;= S and S &amp;lt;= 59) then&lt;br /&gt;
				days_hms = hms({ hour = H, minute = M, second = S })&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if days_hms or not (1 &amp;lt;= d and d &amp;lt;= days_in_month(y, m, calendar)) then&lt;br /&gt;
			date = date or Date(y, m, 1)&lt;br /&gt;
			if not date then return end&lt;br /&gt;
			date = date + (d - 1 + (days_hms or 0))&lt;br /&gt;
			y, m, d = date.year, date.month, date.day&lt;br /&gt;
			if days_hms then&lt;br /&gt;
				H, M, S = date.hour, date.minute, date.second&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	numbers.year = y&lt;br /&gt;
	numbers.month = m&lt;br /&gt;
	numbers.day = d&lt;br /&gt;
	if days_hms then&lt;br /&gt;
		-- Don&#039;t set H unless it was valid because a valid H will set hastime.&lt;br /&gt;
		numbers.hour = H&lt;br /&gt;
		numbers.minute = M&lt;br /&gt;
		numbers.second = S&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function set_date_from_numbers(date, numbers, options)&lt;br /&gt;
	-- Set the fields of table date from numeric values.&lt;br /&gt;
	-- Return true if date is valid.&lt;br /&gt;
	if type(numbers) ~= &#039;table&#039; then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	local y = numbers.year   or date.year&lt;br /&gt;
	local m = numbers.month  or date.month&lt;br /&gt;
	local d = numbers.day    or date.day&lt;br /&gt;
	local H = numbers.hour&lt;br /&gt;
	local M = numbers.minute or date.minute or 0&lt;br /&gt;
	local S = numbers.second or date.second or 0&lt;br /&gt;
	local need_fix&lt;br /&gt;
	if y and m and d then&lt;br /&gt;
		date.partial = nil&lt;br /&gt;
		if not (-9999 &amp;lt;= y and y &amp;lt;= 9999 and&lt;br /&gt;
			1 &amp;lt;= m and m &amp;lt;= 12 and&lt;br /&gt;
			1 &amp;lt;= d and d &amp;lt;= days_in_month(y, m, date.calendar)) then&lt;br /&gt;
				if not date.want_fix then&lt;br /&gt;
					return&lt;br /&gt;
				end&lt;br /&gt;
				need_fix = true&lt;br /&gt;
		end&lt;br /&gt;
	elseif y and date.partial then&lt;br /&gt;
		if d or not (-9999 &amp;lt;= y and y &amp;lt;= 9999) then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
		if m and not (1 &amp;lt;= m and m &amp;lt;= 12) then&lt;br /&gt;
			if not date.want_fix then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
			need_fix = true&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	if date.partial then&lt;br /&gt;
		H = nil  -- ignore any time&lt;br /&gt;
		M = nil&lt;br /&gt;
		S = nil&lt;br /&gt;
	else&lt;br /&gt;
		if H then&lt;br /&gt;
			-- It is not possible to set M or S without also setting H.&lt;br /&gt;
			date.hastime = true&lt;br /&gt;
		else&lt;br /&gt;
			H = 0&lt;br /&gt;
		end&lt;br /&gt;
		if not (0 &amp;lt;= H and H &amp;lt;= 23 and&lt;br /&gt;
				0 &amp;lt;= M and M &amp;lt;= 59 and&lt;br /&gt;
				0 &amp;lt;= S and S &amp;lt;= 59) then&lt;br /&gt;
			if date.want_fix then&lt;br /&gt;
				need_fix = true&lt;br /&gt;
			else&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	date.want_fix = nil&lt;br /&gt;
	if need_fix then&lt;br /&gt;
		fix_numbers(numbers, y, m, d, H, M, S, date.partial, date.hastime, date.calendar)&lt;br /&gt;
		return set_date_from_numbers(date, numbers, options)&lt;br /&gt;
	end&lt;br /&gt;
	date.year = y    -- -9999 to 9999 (&#039;n BC&#039; → year = 1 - n)&lt;br /&gt;
	date.month = m   -- 1 to 12 (may be nil if partial)&lt;br /&gt;
	date.day = d     -- 1 to 31 (* = nil if partial)&lt;br /&gt;
	date.hour = H    -- 0 to 59 (*)&lt;br /&gt;
	date.minute = M  -- 0 to 59 (*)&lt;br /&gt;
	date.second = S  -- 0 to 59 (*)&lt;br /&gt;
	if type(options) == &#039;table&#039; then&lt;br /&gt;
		for _, k in ipairs({ &#039;am&#039;, &#039;era&#039;, &#039;format&#039; }) do&lt;br /&gt;
			if options[k] then&lt;br /&gt;
				date.options[k] = options[k]&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function make_option_table(options1, options2)&lt;br /&gt;
	-- If options1 is a string, return a table with its settings, or&lt;br /&gt;
	-- if it is a table, use its settings.&lt;br /&gt;
	-- Missing options are set from table options2 or defaults.&lt;br /&gt;
	-- If a default is used, a flag is set so caller knows the value was not intentionally set.&lt;br /&gt;
	-- Valid option settings are:&lt;br /&gt;
	-- am: &#039;am&#039;, &#039;a.m.&#039;, &#039;AM&#039;, &#039;A.M.&#039;&lt;br /&gt;
	--     &#039;pm&#039;, &#039;p.m.&#039;, &#039;PM&#039;, &#039;P.M.&#039; (each has same meaning as corresponding item above)&lt;br /&gt;
	-- era: &#039;BCMINUS&#039;, &#039;BCNEGATIVE&#039;, &#039;BC&#039;, &#039;B.C.&#039;, &#039;BCE&#039;, &#039;B.C.E.&#039;, &#039;AD&#039;, &#039;A.D.&#039;, &#039;CE&#039;, &#039;C.E.&#039;&lt;br /&gt;
	-- Option am = &#039;am&#039; does not mean the hour is AM; it means &#039;am&#039; or &#039;pm&#039; is used, depending on the hour,&lt;br /&gt;
	--    and am = &#039;pm&#039; has the same meaning.&lt;br /&gt;
	-- Similarly, era = &#039;BC&#039; means &#039;BC&#039; is used if year &amp;lt;= 0.&lt;br /&gt;
	-- BCMINUS displays a MINUS if year &amp;lt; 0 and the display format does not include %{era}.&lt;br /&gt;
	-- BCNEGATIVE is similar but displays a hyphen.&lt;br /&gt;
	local result = { bydefault = {} }&lt;br /&gt;
	if type(options1) == &#039;table&#039; then&lt;br /&gt;
		result.am = options1.am&lt;br /&gt;
		result.era = options1.era&lt;br /&gt;
	elseif type(options1) == &#039;string&#039; then&lt;br /&gt;
		-- Example: &#039;am:AM era:BC&#039; or &#039;am=AM era=BC&#039;.&lt;br /&gt;
		for item in options1:gmatch(&#039;%S+&#039;) do&lt;br /&gt;
			local lhs, rhs = item:match(&#039;^(%w+)[:=](.+)$&#039;)&lt;br /&gt;
			if lhs then&lt;br /&gt;
				result[lhs] = rhs&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	options2 = type(options2) == &#039;table&#039; and options2 or {}&lt;br /&gt;
	local defaults = { am = &#039;am&#039;, era = &#039;a. C.&#039; }&lt;br /&gt;
	for k, v in pairs(defaults) do&lt;br /&gt;
		if not result[k] then&lt;br /&gt;
			if options2[k] then&lt;br /&gt;
				result[k] = options2[k]&lt;br /&gt;
			else&lt;br /&gt;
				result[k] = v&lt;br /&gt;
				result.bydefault[k] = true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local ampm_options = {&lt;br /&gt;
	-- lhs = input text accepted as an am/pm option&lt;br /&gt;
	-- rhs = code used internally&lt;br /&gt;
	[&#039;am&#039;]   = &#039;am&#039;,&lt;br /&gt;
	[&#039;AM&#039;]   = &#039;AM&#039;,&lt;br /&gt;
	[&#039;a.m.&#039;] = &#039;a.m.&#039;,&lt;br /&gt;
	[&#039;A.M.&#039;] = &#039;A.M.&#039;,&lt;br /&gt;
	[&#039;pm&#039;]   = &#039;am&#039;,  -- same as am&lt;br /&gt;
	[&#039;PM&#039;]   = &#039;AM&#039;,&lt;br /&gt;
	[&#039;p.m.&#039;] = &#039;a.m.&#039;,&lt;br /&gt;
	[&#039;P.M.&#039;] = &#039;A.M.&#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local era_text = {&lt;br /&gt;
	-- Text for displaying an era with a positive year (after adjusting&lt;br /&gt;
	-- by replacing year with 1 - year if date.year &amp;lt;= 0).&lt;br /&gt;
	-- options.era = { year&amp;lt;=0 , year&amp;gt;0 }&lt;br /&gt;
	[&#039;BCMINUS&#039;]    = { &#039;BC&#039;    , &#039;&#039;    , isbc = true, sign = MINUS },&lt;br /&gt;
	[&#039;BCNEGATIVE&#039;] = { &#039;BC&#039;    , &#039;&#039;    , isbc = true, sign = &#039;-&#039;   },&lt;br /&gt;
	[&#039;BC&#039;]         = { &#039;BC&#039;    , &#039;&#039;    , isbc = true },&lt;br /&gt;
	[&#039;B.C.&#039;]       = { &#039;B.C.&#039;  , &#039;&#039;    , isbc = true },&lt;br /&gt;
	[&#039;BCE&#039;]        = { &#039;BCE&#039;   , &#039;&#039;    , isbc = true },&lt;br /&gt;
	[&#039;B.C.E.&#039;]     = { &#039;B.C.E.&#039;, &#039;&#039;    , isbc = true },&lt;br /&gt;
	[&#039;AD&#039;]         = { &#039;BC&#039;    , &#039;AD&#039;   },&lt;br /&gt;
	[&#039;A.D.&#039;]       = { &#039;B.C.&#039;  , &#039;A.D.&#039; },&lt;br /&gt;
	[&#039;CE&#039;]         = { &#039;BCE&#039;   , &#039;CE&#039;   },&lt;br /&gt;
	[&#039;C.E.&#039;]       = { &#039;B.C.E.&#039;, &#039;C.E.&#039; },&lt;br /&gt;
	--ABREVIATURAS EN ESPAÑOL--&lt;br /&gt;
	[&#039;a. C.&#039;]         = { &#039;a. C.&#039;       , &#039;&#039;    , isbc = true },  --antes de Cristo&lt;br /&gt;
	[&#039;a. de C.&#039;]      = { &#039;a. de C.&#039;    , &#039;&#039;    , isbc = true },  --antes de Cristo&lt;br /&gt;
	[&#039;a. de J. C.&#039;]   = { &#039;a. de J. C.&#039; , &#039;&#039;    , isbc = true },  --antes de Jesucristo&lt;br /&gt;
	[&#039;a. J. C.&#039;]      = { &#039;a. J. C.&#039;    , &#039;&#039;    , isbc = true },  --antes de Jesucristo&lt;br /&gt;
	[&#039;AEC&#039;]           = { &#039;AEC&#039;         , &#039;&#039;    , isbc = true },  --antes de la era común&lt;br /&gt;
	[&#039;a. e. c.&#039;]      = { &#039;a. e. c.&#039;    , &#039;&#039;    , isbc = true },  --antes de la era común&lt;br /&gt;
	[&#039;a. n. e.&#039;]      = { &#039;a. n. e.&#039;    , &#039;&#039;    , isbc = true },  --antes de nuestra era&lt;br /&gt;
	[&#039;a. e. v.&#039;]      = { &#039;a. e. v.&#039;    , &#039;&#039;    , isbc = true },  --antes de la era vulgar&lt;br /&gt;
	[&#039;d. C.&#039;]         = { &#039;a. C.&#039;       , &#039;d. C.&#039; },              --después de Cristo&lt;br /&gt;
	[&#039;d. de C.&#039;]      = { &#039;a. de C.&#039;    , &#039;d. de C.&#039; },           --después de Cristo&lt;br /&gt;
	[&#039;d. de J. C.&#039;]   = { &#039;a. de J. C.&#039; , &#039;d. de J. C.&#039; },        --después de Jesucristo&lt;br /&gt;
	[&#039;d. J. C.&#039;]      = { &#039;a. J. C.&#039;    , &#039;d. J. C.&#039; },           --después de Jesucristo&lt;br /&gt;
	[&#039;EC&#039;]            = { &#039;AEC&#039;         , &#039;EC&#039; },                 --era común&lt;br /&gt;
	[&#039;e. c.&#039;]         = { &#039;a. e. c.&#039;    , &#039;e. c.&#039; },              --era común&lt;br /&gt;
	[&#039;n. e.&#039;]         = { &#039;a. n. e.&#039;    , &#039;n. e.&#039; },              --nuestra era&lt;br /&gt;
	[&#039;e. v.&#039;]         = { &#039;a. e. v.&#039;    , &#039;e. v.&#039; },              --era vulgar&lt;br /&gt;
	[&#039;A. D.&#039;]         = { &#039;a. C.&#039;       , &#039;A. D.&#039; },              --anno Domini&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function get_era_for_year(era, year)&lt;br /&gt;
	return (era_text[era] or era_text[&#039;a. C.&#039;])[year &amp;gt; 0 and 2 or 1]:gsub(&amp;quot; &amp;quot;, &amp;quot;&amp;amp;nbsp;&amp;quot;) or &#039;&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function strftime(date, format, options)&lt;br /&gt;
	-- Return date formatted as a string using codes similar to those&lt;br /&gt;
	-- in the C strftime library function.&lt;br /&gt;
	local sformat = string.format&lt;br /&gt;
	local shortcuts = {&lt;br /&gt;
		[&#039;%c&#039;] = &#039;%-I:%M %p %-d de %B de %-Y %{era}&#039;,  -- date and time: 2:30 pm 1 de abril de 2016&lt;br /&gt;
		[&#039;%C&#039;] = &#039;%-d de %B de %-Y, %H:%M:%S&#039;,	   -- date and time: 1 de abril de 2016, 14:30&lt;br /&gt;
		[&#039;%x&#039;] = &#039;%-d de %B de %-Y %{era}&#039;,            -- date:          1 de abril de 2016&lt;br /&gt;
		[&#039;%X&#039;] = &#039;%-I:%M %p&#039;,                          -- time:          2:30 pm&lt;br /&gt;
	}&lt;br /&gt;
	if shortcuts[format] then&lt;br /&gt;
		format = shortcuts[format]&lt;br /&gt;
	end&lt;br /&gt;
	local codes = {&lt;br /&gt;
		a = { field = &#039;dayabbr&#039; },&lt;br /&gt;
		A = { field = &#039;dayname&#039; },&lt;br /&gt;
		b = { field = &#039;monthabbr&#039; },&lt;br /&gt;
		B = { field = &#039;monthname&#039; },&lt;br /&gt;
		u = { fmt = &#039;%d&#039;  , field = &#039;dowiso&#039; },&lt;br /&gt;
		w = { fmt = &#039;%d&#039;  , field = &#039;dow&#039; },&lt;br /&gt;
		d = { fmt = &#039;%02d&#039;, fmt2 = &#039;%d&#039;, field = &#039;day&#039; },&lt;br /&gt;
		m = { fmt = &#039;%02d&#039;, fmt2 = &#039;%d&#039;, field = &#039;month&#039; },&lt;br /&gt;
		Y = { fmt = &#039;%04d&#039;, fmt2 = &#039;%d&#039;, field = &#039;year&#039; },&lt;br /&gt;
		H = { fmt = &#039;%02d&#039;, fmt2 = &#039;%d&#039;, field = &#039;hour&#039; },&lt;br /&gt;
		M = { fmt = &#039;%02d&#039;, fmt2 = &#039;%d&#039;, field = &#039;minute&#039; },&lt;br /&gt;
		S = { fmt = &#039;%02d&#039;, fmt2 = &#039;%d&#039;, field = &#039;second&#039; },&lt;br /&gt;
		j = { fmt = &#039;%03d&#039;, fmt2 = &#039;%d&#039;, field = &#039;dayofyear&#039; },&lt;br /&gt;
		I = { fmt = &#039;%02d&#039;, fmt2 = &#039;%d&#039;, field = &#039;hour&#039;, special = &#039;hour12&#039; },&lt;br /&gt;
		p = { field = &#039;hour&#039;, special = &#039;am&#039; },&lt;br /&gt;
	}&lt;br /&gt;
	options = make_option_table(options, date.options)&lt;br /&gt;
	local amopt = options.am&lt;br /&gt;
	local eraopt = options.era&lt;br /&gt;
	local function replace_code(spaces, modifier, id)&lt;br /&gt;
		local code = codes[id]&lt;br /&gt;
		if code then&lt;br /&gt;
			local fmt = code.fmt&lt;br /&gt;
			if modifier == &#039;-&#039; and code.fmt2 then&lt;br /&gt;
				fmt = code.fmt2&lt;br /&gt;
			end&lt;br /&gt;
			local value = date[code.field]&lt;br /&gt;
			if not value then&lt;br /&gt;
				return nil  -- an undefined field in a partial date&lt;br /&gt;
			end&lt;br /&gt;
			local special = code.special&lt;br /&gt;
			if special then&lt;br /&gt;
				if special == &#039;hour12&#039; then&lt;br /&gt;
					value = value % 12&lt;br /&gt;
					value = value == 0 and 12 or value&lt;br /&gt;
				elseif special == &#039;am&#039; then&lt;br /&gt;
					local ap = ({&lt;br /&gt;
						[&#039;a.m.&#039;] = { &#039;a.m.&#039;, &#039;p.m.&#039; },&lt;br /&gt;
						[&#039;AM&#039;] = { &#039;AM&#039;, &#039;PM&#039; },&lt;br /&gt;
						[&#039;A.M.&#039;] = { &#039;A.M.&#039;, &#039;P.M.&#039; },&lt;br /&gt;
					})[ampm_options[amopt]] or { &#039;am&#039;, &#039;pm&#039; }&lt;br /&gt;
					return (spaces == &#039;&#039; and &#039;&#039; or &#039;&amp;amp;nbsp;&#039;) .. (value &amp;lt; 12 and ap[1] or ap[2])&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if code.field == &#039;year&#039; then&lt;br /&gt;
				local sign = (era_text[eraopt] or {}).sign&lt;br /&gt;
				if not sign or format:find(&#039;%{era}&#039;, 1, true) then&lt;br /&gt;
					sign = &#039;&#039;&lt;br /&gt;
					if value &amp;lt;= 0 then&lt;br /&gt;
						value = 1 - value&lt;br /&gt;
					end&lt;br /&gt;
				else&lt;br /&gt;
					if value &amp;gt;= 0 then&lt;br /&gt;
						sign = &#039;&#039;&lt;br /&gt;
					else&lt;br /&gt;
						value = -value&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				return spaces .. sign .. sformat(fmt, value)&lt;br /&gt;
			end&lt;br /&gt;
			return spaces .. (fmt and sformat(fmt, value) or value)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local function replace_property(spaces, id)&lt;br /&gt;
		if id == &#039;era&#039; then&lt;br /&gt;
			-- Special case so can use local era option.&lt;br /&gt;
			local result = get_era_for_year(eraopt, date.year)&lt;br /&gt;
			if result == &#039;&#039; then&lt;br /&gt;
				return &#039;&#039;&lt;br /&gt;
			end&lt;br /&gt;
			return (spaces == &#039;&#039; and &#039;&#039; or &#039;&amp;amp;nbsp;&#039;) .. result&lt;br /&gt;
		end&lt;br /&gt;
		local result = date[id]&lt;br /&gt;
		if type(result) == &#039;string&#039; then&lt;br /&gt;
			return spaces .. result&lt;br /&gt;
		end&lt;br /&gt;
		if type(result) == &#039;number&#039; then&lt;br /&gt;
			return  spaces .. tostring(result)&lt;br /&gt;
		end&lt;br /&gt;
		if type(result) == &#039;boolean&#039; then&lt;br /&gt;
			return  spaces .. (result and &#039;1&#039; or &#039;0&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		-- This occurs if id is an undefined field in a partial date, or is the name of a function.&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local PERCENT = &#039;\127PERCENT\127&#039;&lt;br /&gt;
	return (format&lt;br /&gt;
		:gsub(&#039;%%%%&#039;, PERCENT)&lt;br /&gt;
		:gsub(&#039;(%s*)%%{(%w+)}&#039;, replace_property)&lt;br /&gt;
		:gsub(&#039;(%s*)%%(%-?)(%a)&#039;, replace_code)&lt;br /&gt;
		:gsub(PERCENT, &#039;%%&#039;)&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function _date_text(date, fmt, options)&lt;br /&gt;
	-- Return a formatted string representing the given date.&lt;br /&gt;
	if not is_date(date) then&lt;br /&gt;
		error(&#039;date:text: need a date (use &amp;quot;date:text()&amp;quot; with a colon)&#039;, 2)&lt;br /&gt;
	end&lt;br /&gt;
	if type(fmt) == &#039;string&#039; and fmt:match(&#039;%S&#039;) then&lt;br /&gt;
		if fmt:find(&#039;%&#039;, 1, true) then&lt;br /&gt;
			return strftime(date, fmt, options)&lt;br /&gt;
		end&lt;br /&gt;
	elseif date.partial then&lt;br /&gt;
		fmt = date.month and &#039;my&#039; or &#039;y&#039;&lt;br /&gt;
	else&lt;br /&gt;
		fmt = &#039;dmy&#039;&lt;br /&gt;
		if date.hastime then&lt;br /&gt;
			fmt = (date.second &amp;gt; 0 and &#039;hms &#039; or &#039;hm &#039;) .. fmt&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local function bad_format()&lt;br /&gt;
		-- For consistency with other format processing, return given format&lt;br /&gt;
		-- (or cleaned format if original was not a string) if invalid.&lt;br /&gt;
		return mw.text.nowiki(fmt)&lt;br /&gt;
	end&lt;br /&gt;
	if date.partial then&lt;br /&gt;
		-- Ignore days in standard formats like &#039;ymd&#039;.&lt;br /&gt;
		if fmt == &#039;ym&#039; or fmt == &#039;ymd&#039; then&lt;br /&gt;
			fmt = date.month and &#039;%Y-%m %{era}&#039; or &#039;%Y %{era}&#039;&lt;br /&gt;
		elseif fmt == &#039;my&#039; or fmt == &#039;dmy&#039; or fmt == &#039;mdy&#039; then&lt;br /&gt;
			fmt = date.month and &#039;%B %-Y %{era}&#039; or &#039;%-Y %{era}&#039;&lt;br /&gt;
		elseif fmt == &#039;y&#039; then&lt;br /&gt;
			fmt = date.month and &#039;%-Y %{era}&#039; or &#039;%-Y %{era}&#039;&lt;br /&gt;
		else&lt;br /&gt;
			return bad_format()&lt;br /&gt;
		end&lt;br /&gt;
		return strftime(date, fmt, options)&lt;br /&gt;
	end&lt;br /&gt;
	local function hm_fmt()&lt;br /&gt;
		local plain = make_option_table(options, date.options).bydefault.am&lt;br /&gt;
		return plain and &#039;%H:%M&#039; or &#039;%-I:%M %p&#039;&lt;br /&gt;
	end&lt;br /&gt;
	local need_time = date.hastime&lt;br /&gt;
	local t = collection()&lt;br /&gt;
	for item in fmt:gmatch(&#039;%S+&#039;) do&lt;br /&gt;
		local f&lt;br /&gt;
		if item == &#039;hm&#039; then&lt;br /&gt;
			f = hm_fmt()&lt;br /&gt;
			need_time = false&lt;br /&gt;
		elseif item == &#039;hms&#039; then&lt;br /&gt;
			f = &#039;%H:%M:%S&#039;&lt;br /&gt;
			need_time = false&lt;br /&gt;
		elseif item == &#039;ymd&#039; then&lt;br /&gt;
			f = &#039;%Y-%m-%d %{era}&#039;&lt;br /&gt;
		elseif item == &#039;mdy&#039; then&lt;br /&gt;
			f = &#039;%B %-d, %-Y %{era}&#039;&lt;br /&gt;
		elseif item == &#039;dmy&#039; then&lt;br /&gt;
			f = &#039;%-d de %B de %-Y %{era}&#039;&lt;br /&gt;
		else&lt;br /&gt;
			return bad_format()&lt;br /&gt;
		end&lt;br /&gt;
		t:add(f)&lt;br /&gt;
	end&lt;br /&gt;
	fmt = t:join(&#039; &#039;)&lt;br /&gt;
	if need_time then&lt;br /&gt;
		fmt = hm_fmt() .. &#039; &#039; .. fmt&lt;br /&gt;
	end&lt;br /&gt;
	return strftime(date, fmt, options)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local day_info = {&lt;br /&gt;
	-- 0=Sun to 6=Sat&lt;br /&gt;
	[0] = { &#039;do&#039;, &#039;domingo&#039; },&lt;br /&gt;
	{ &#039;lu&#039;, &#039;lunes&#039; },&lt;br /&gt;
	{ &#039;ma&#039;, &#039;martes&#039; },&lt;br /&gt;
	{ &#039;mi&#039;, &#039;miércoles&#039; },&lt;br /&gt;
	{ &#039;ju&#039;, &#039;jueves&#039; },&lt;br /&gt;
	{ &#039;vi&#039;, &#039;viernes&#039; },&lt;br /&gt;
	{ &#039;sa&#039;, &#039;sábado&#039; },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local month_info = {&lt;br /&gt;
	-- 1=Jan to 12=Dec&lt;br /&gt;
	{ &#039;ene&#039;, &#039;enero&#039; },&lt;br /&gt;
	{ &#039;feb&#039;, &#039;febrero&#039; },&lt;br /&gt;
	{ &#039;mar&#039;, &#039;marzo&#039; },&lt;br /&gt;
	{ &#039;abr&#039;, &#039;abril&#039; },&lt;br /&gt;
	{ &#039;may&#039;, &#039;mayo&#039; },&lt;br /&gt;
	{ &#039;jun&#039;, &#039;junio&#039; },&lt;br /&gt;
	{ &#039;jul&#039;, &#039;julio&#039; },&lt;br /&gt;
	{ &#039;ago&#039;, &#039;agosto&#039; },&lt;br /&gt;
	{ &#039;sep&#039;, &#039;septiembre&#039; },&lt;br /&gt;
	{ &#039;oct&#039;, &#039;octubre&#039; },&lt;br /&gt;
	{ &#039;nov&#039;, &#039;noviembre&#039; },&lt;br /&gt;
	{ &#039;dic&#039;, &#039;diciembre&#039; },&lt;br /&gt;
}&lt;br /&gt;
for k,v in pairs(month_info) do month_info[ v[1] ], month_info[ v[2] ] = v, v end&lt;br /&gt;
&lt;br /&gt;
local function name_to_number(text, translate)&lt;br /&gt;
	if type(text) == &#039;string&#039; then&lt;br /&gt;
		return translate[&#039;xx&#039; .. text:lower():gsub(&#039;é&#039;, &#039;e&#039;):gsub(&#039;á&#039;, &#039;a&#039;)]&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function day_number(text)&lt;br /&gt;
	return name_to_number(text, {&lt;br /&gt;
		xxdo = 0, xxdomingo = 0, &lt;br /&gt;
		xxlu = 1, xxlunes = 1, xxlune = 1,&lt;br /&gt;
		xxma = 2, xxmartes = 2, xxmarte = 2,&lt;br /&gt;
		xxmi = 3, xxmiercoles = 3, xxmiercole = 3,&lt;br /&gt;
		xxju = 4, xxjueves = 4, xxjueve = 4,&lt;br /&gt;
		xxvi = 5, xxviernes = 5, xxvierne = 5,&lt;br /&gt;
		xxsat = 6, xxsabado = 6&lt;br /&gt;
	})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function month_number(text)&lt;br /&gt;
	return name_to_number(text, {&lt;br /&gt;
		xxene = 1, xxenero = 1,&lt;br /&gt;
		xxfeb = 2, xxfebrero = 2,&lt;br /&gt;
		xxmar = 3, xxmarzo = 3,&lt;br /&gt;
		xxabr = 4, xxabril = 4,&lt;br /&gt;
		xxmay = 5, xxmayo = 5,&lt;br /&gt;
		xxjun = 6, xxjunio = 6,&lt;br /&gt;
		xxjul = 7, xxjulio = 7,&lt;br /&gt;
		xxago = 8, xxagosto = 8,&lt;br /&gt;
		xxsep = 9, xxseptiembre = 9, xxsept = 9,&lt;br /&gt;
		xxoct = 10, xxoctubre = 10,&lt;br /&gt;
		xxnov = 11, xxnoviembre = 11,&lt;br /&gt;
		xxdic = 12, xxdiciembre = 12,&lt;br /&gt;
	})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function _list_text(list, fmt)&lt;br /&gt;
	-- Return a list of formatted strings from a list of dates.&lt;br /&gt;
	if not type(list) == &#039;table&#039; then&lt;br /&gt;
		error(&#039;date:list:text: need &amp;quot;list:text()&amp;quot; with a colon&#039;, 2)&lt;br /&gt;
	end&lt;br /&gt;
	local result = { join = _list_join }&lt;br /&gt;
	for i, date in ipairs(list) do&lt;br /&gt;
		result[i] = date:text(fmt)&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function _date_list(date, spec)&lt;br /&gt;
	-- Return a possibly empty numbered table of dates meeting the specification.&lt;br /&gt;
	-- Dates in the list are in ascending order (oldest date first).&lt;br /&gt;
	-- The spec should be a string of form &amp;quot;&amp;lt;count&amp;gt; &amp;lt;day&amp;gt; &amp;lt;op&amp;gt;&amp;quot;&lt;br /&gt;
	-- where each item is optional and&lt;br /&gt;
	--   count = number of items wanted in list&lt;br /&gt;
	--   day = abbreviation or name such as Mon or Monday&lt;br /&gt;
	--   op = &amp;gt;, &amp;gt;=, &amp;lt;, &amp;lt;= (default is &amp;gt; meaning after date)&lt;br /&gt;
	-- If no count is given, the list is for the specified days in date&#039;s month.&lt;br /&gt;
	-- The default day is date&#039;s day.&lt;br /&gt;
	-- The spec can also be a positive or negative number:&lt;br /&gt;
	--   -5 is equivalent to &#039;5 &amp;lt;&#039;&lt;br /&gt;
	--   5  is equivalent to &#039;5&#039; which is &#039;5 &amp;gt;&#039;&lt;br /&gt;
	if not is_date(date) then&lt;br /&gt;
		error(&#039;date:list: need a date (use &amp;quot;date:list()&amp;quot; with a colon)&#039;, 2)&lt;br /&gt;
	end&lt;br /&gt;
	local list = { text = _list_text }&lt;br /&gt;
	if date.partial then&lt;br /&gt;
		return list&lt;br /&gt;
	end&lt;br /&gt;
	local count, offset, operation&lt;br /&gt;
	local ops = {&lt;br /&gt;
		[&#039;&amp;gt;=&#039;] = { before = false, include = true  },&lt;br /&gt;
		[&#039;&amp;gt;&#039;]  = { before = false, include = false },&lt;br /&gt;
		[&#039;&amp;lt;=&#039;] = { before = true , include = true  },&lt;br /&gt;
		[&#039;&amp;lt;&#039;]  = { before = true , include = false },&lt;br /&gt;
	}&lt;br /&gt;
	if spec then&lt;br /&gt;
		if type(spec) == &#039;number&#039; then&lt;br /&gt;
			count = floor(spec + 0.5)&lt;br /&gt;
			if count &amp;lt; 0 then&lt;br /&gt;
				count = -count&lt;br /&gt;
				operation = ops[&#039;&amp;lt;&#039;]&lt;br /&gt;
			end&lt;br /&gt;
		elseif type(spec) == &#039;string&#039; then&lt;br /&gt;
			local num, day, op = spec:match(&#039;^%s*(%d*)%s*(%a*)%s*([&amp;lt;&amp;gt;=]*)%s*$&#039;)&lt;br /&gt;
			if not num then&lt;br /&gt;
				return list&lt;br /&gt;
			end&lt;br /&gt;
			if num ~= &#039;&#039; then&lt;br /&gt;
				count = tonumber(num)&lt;br /&gt;
			end&lt;br /&gt;
			if day ~= &#039;&#039; then&lt;br /&gt;
				local dow = day_number(day:gsub(&#039;[sS]$&#039;, &#039;&#039;))  -- accept plural days&lt;br /&gt;
				if not dow then&lt;br /&gt;
					return list&lt;br /&gt;
				end&lt;br /&gt;
				offset = dow - date.dow&lt;br /&gt;
			end&lt;br /&gt;
			operation = ops[op]&lt;br /&gt;
		else&lt;br /&gt;
			return list&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	offset = offset or 0&lt;br /&gt;
	operation = operation or ops[&#039;&amp;gt;&#039;]&lt;br /&gt;
	local datefrom, dayfirst, daylast&lt;br /&gt;
	if operation.before then&lt;br /&gt;
		if offset &amp;gt; 0 or (offset == 0 and not operation.include) then&lt;br /&gt;
			offset = offset - 7&lt;br /&gt;
		end&lt;br /&gt;
		if count then&lt;br /&gt;
			if count &amp;gt; 1 then&lt;br /&gt;
				offset = offset - 7*(count - 1)&lt;br /&gt;
			end&lt;br /&gt;
			datefrom = date + offset&lt;br /&gt;
		else&lt;br /&gt;
			daylast = date.day + offset&lt;br /&gt;
			dayfirst = daylast % 7&lt;br /&gt;
			if dayfirst == 0 then&lt;br /&gt;
				dayfirst = 7&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		if offset &amp;lt; 0 or (offset == 0 and not operation.include) then&lt;br /&gt;
			offset = offset + 7&lt;br /&gt;
		end&lt;br /&gt;
		if count then&lt;br /&gt;
			datefrom = date + offset&lt;br /&gt;
		else&lt;br /&gt;
			dayfirst = date.day + offset&lt;br /&gt;
			daylast = date.monthdays&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if not count then&lt;br /&gt;
		if daylast &amp;lt; dayfirst then&lt;br /&gt;
			return list&lt;br /&gt;
		end&lt;br /&gt;
		count = floor((daylast - dayfirst)/7) + 1&lt;br /&gt;
		datefrom = Date(date, {day = dayfirst})&lt;br /&gt;
	end&lt;br /&gt;
	for i = 1, count do&lt;br /&gt;
		if not datefrom then break end  -- exceeds date limits&lt;br /&gt;
		list[i] = datefrom&lt;br /&gt;
		datefrom = datefrom + 7&lt;br /&gt;
	end&lt;br /&gt;
	return list&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- A table to get the current date/time (UTC), but only if needed.&lt;br /&gt;
local current = setmetatable({}, {&lt;br /&gt;
	__index = function (self, key)&lt;br /&gt;
		local d = os.date(&#039;!*t&#039;)&lt;br /&gt;
		self.year = d.year&lt;br /&gt;
		self.month = d.month&lt;br /&gt;
		self.day = d.day&lt;br /&gt;
		self.hour = d.hour&lt;br /&gt;
		self.minute = d.min&lt;br /&gt;
		self.second = d.sec&lt;br /&gt;
		return rawget(self, key)&lt;br /&gt;
	end })&lt;br /&gt;
&lt;br /&gt;
local function extract_date(newdate, text)&lt;br /&gt;
	-- Parse the date/time in text and return n, o where&lt;br /&gt;
	--   n = table of numbers with date/time fields&lt;br /&gt;
	--   o = table of options for AM/PM or AD/BC or format, if any&lt;br /&gt;
	-- or return nothing if date is known to be invalid.&lt;br /&gt;
	-- Caller determines if the values in n are valid.&lt;br /&gt;
	-- A year must be positive (&#039;1&#039; to &#039;9999&#039;); use &#039;BC&#039; for BC.&lt;br /&gt;
	-- In a y-m-d string, the year must be four digits to avoid ambiguity&lt;br /&gt;
	-- (&#039;0001&#039; to &#039;9999&#039;). The only way to enter year &amp;lt;= 0 is by specifying&lt;br /&gt;
	-- the date as three numeric parameters like ymd Date(-1, 1, 1).&lt;br /&gt;
	-- Dates of form d/m/y, m/d/y, y/m/d are [partially] rejected as potentially ambiguous.&lt;br /&gt;
	local date, options = {}, {}&lt;br /&gt;
	if text:sub(-1) == &#039;Z&#039; then&lt;br /&gt;
		-- Extract date/time from a Wikidata timestamp.&lt;br /&gt;
		-- The year can be 1 to 16 digits but this module handles 1 to 4 digits only.&lt;br /&gt;
		-- Examples: &#039;+2016-06-21T14:30:00Z&#039;, &#039;-0000000180-00-00T00:00:00Z&#039;.&lt;br /&gt;
		local sign, y, m, d, H, M, S = text:match(&#039;^([+%-])(%d+)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)Z$&#039;)&lt;br /&gt;
		if sign then&lt;br /&gt;
			y = tonumber(y)&lt;br /&gt;
			if sign == &#039;-&#039; and y &amp;gt; 0 then&lt;br /&gt;
				y = -y&lt;br /&gt;
			end&lt;br /&gt;
			if y &amp;lt;= 0 then&lt;br /&gt;
				options.era = &#039;a. C.&#039; -- Sets the era when the year is negative on the timestamp&lt;br /&gt;
			end&lt;br /&gt;
			date.year = y&lt;br /&gt;
			m = tonumber(m)&lt;br /&gt;
			d = tonumber(d)&lt;br /&gt;
			H = tonumber(H)&lt;br /&gt;
			M = tonumber(M)&lt;br /&gt;
			S = tonumber(S)&lt;br /&gt;
			if m == 0 then&lt;br /&gt;
				newdate.partial = true&lt;br /&gt;
				return date, options&lt;br /&gt;
			end&lt;br /&gt;
			date.month = m&lt;br /&gt;
			if d == 0 then&lt;br /&gt;
				newdate.partial = true&lt;br /&gt;
				return date, options&lt;br /&gt;
			end&lt;br /&gt;
			date.day = d&lt;br /&gt;
			if H &amp;gt; 0 or M &amp;gt; 0 or S &amp;gt; 0 then&lt;br /&gt;
				date.hour = H&lt;br /&gt;
				date.minute = M&lt;br /&gt;
				date.second = S&lt;br /&gt;
			end&lt;br /&gt;
			return date, options&lt;br /&gt;
		end&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local a, b, c = text:match(&#039;^(%d+)[-./](%d+)[-./](%d+)$&#039;)&lt;br /&gt;
	if a --[[ and b and c --]] then&lt;br /&gt;
		a = tonumber(a)&lt;br /&gt;
		b = tonumber(b)&lt;br /&gt;
		c = tonumber(c)&lt;br /&gt;
		--[[ -- use extract_ymd for this&lt;br /&gt;
		if a &amp;gt; 31 and m &amp;lt;= 12 and c &amp;gt; 12 then&lt;br /&gt;
			date.year, date.month, date.day = a, b, c&lt;br /&gt;
			options.format = &#039;ymd&#039;&lt;br /&gt;
			newdate.partial = true&lt;br /&gt;
			return date, options&lt;br /&gt;
		else--]]&lt;br /&gt;
		if a &amp;gt; 12 and b &amp;lt;= 12 and c &amp;gt; 31 then&lt;br /&gt;
			date.year, date.month, date.day = c, b, a&lt;br /&gt;
			options.format = &#039;dmy&#039;&lt;br /&gt;
			newdate.partial = true&lt;br /&gt;
			return date, options&lt;br /&gt;
		elseif a &amp;lt;= 12 and b &amp;gt; 12 and c &amp;gt; 31 then&lt;br /&gt;
			date.year, date.month, date.day = c, a, b&lt;br /&gt;
			options.format = &#039;mdy&#039;&lt;br /&gt;
			newdate.partial = true&lt;br /&gt;
			return date, options&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function extract_ymd(item)&lt;br /&gt;
		-- Called when no day or month has been set.&lt;br /&gt;
		local y, m, d = item:match(&#039;^(%d%d%d%d)[-./](%w+)[-./](%d%d?)$&#039;)&lt;br /&gt;
		if y then&lt;br /&gt;
			if date.year then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
			if m:match(&#039;^%d%d?$&#039;) then&lt;br /&gt;
				m = tonumber(m)&lt;br /&gt;
			else&lt;br /&gt;
				m = month_number(m)&lt;br /&gt;
			end&lt;br /&gt;
			if m then&lt;br /&gt;
				date.year = tonumber(y)&lt;br /&gt;
				date.month = m&lt;br /&gt;
				date.day = tonumber(d)&lt;br /&gt;
				return true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local function extract_day_or_year(item)&lt;br /&gt;
		-- Called when a day would be valid, or&lt;br /&gt;
		-- when a year would be valid if no year has been set and partial is set.&lt;br /&gt;
		local number, suffix = item:match(&#039;^(%d%d?%d?%d?)(.*)$&#039;)&lt;br /&gt;
		if number then&lt;br /&gt;
			local n = tonumber(number)&lt;br /&gt;
			if #number &amp;lt;= 2 and n &amp;lt;= 31 then&lt;br /&gt;
				suffix = suffix:lower()&lt;br /&gt;
				if suffix == &#039;&#039; or suffix == &#039;st&#039; or suffix == &#039;nd&#039; or suffix == &#039;rd&#039; or suffix == &#039;th&#039; then&lt;br /&gt;
					date.day = n&lt;br /&gt;
					return true&lt;br /&gt;
				end&lt;br /&gt;
			elseif suffix == &#039;&#039; and newdate.partial and not date.year then&lt;br /&gt;
				date.year = n&lt;br /&gt;
				return true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local function extract_month(item)&lt;br /&gt;
		-- A month must be given as a name or abbreviation; a number could be ambiguous.&lt;br /&gt;
		local m = month_number(item)&lt;br /&gt;
		if m then&lt;br /&gt;
			date.month = m&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local function extract_time(item)&lt;br /&gt;
		local h, m, s = item:match(&#039;^(%d%d?):(%d%d)(:?%d*)$&#039;)&lt;br /&gt;
		if date.hour or not h then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
		if s ~= &#039;&#039; then&lt;br /&gt;
			s = s:match(&#039;^:(%d%d)$&#039;)&lt;br /&gt;
			if not s then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		date.hour = tonumber(h)&lt;br /&gt;
		date.minute = tonumber(m)&lt;br /&gt;
		date.second = tonumber(s)  -- nil if empty string&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	local item_count = 0&lt;br /&gt;
	local index_time&lt;br /&gt;
	local function set_ampm(item)&lt;br /&gt;
		local H = date.hour&lt;br /&gt;
		if H and not options.am and index_time + 1 == item_count then&lt;br /&gt;
			options.am = ampm_options[item]  -- caller checked this is not nil&lt;br /&gt;
			if item:match(&#039;^[Aa]&#039;) then&lt;br /&gt;
				if not (1 &amp;lt;= H and H &amp;lt;= 12) then&lt;br /&gt;
					return&lt;br /&gt;
				end&lt;br /&gt;
				if H == 12 then&lt;br /&gt;
					date.hour = 0&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				if not (1 &amp;lt;= H and H &amp;lt;= 23) then&lt;br /&gt;
					return&lt;br /&gt;
				end&lt;br /&gt;
				if H &amp;lt;= 11 then&lt;br /&gt;
					date.hour = H + 12&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
    --Filtrar abreviaturas de era&lt;br /&gt;
	for key,value in pairs(era_text) do&lt;br /&gt;
		if string.find(text, key) ~= nil then&lt;br /&gt;
			options.era = key&lt;br /&gt;
			text = string.gsub(text, key, &#039;&#039;)&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for item in text:gsub(&#039;,&#039;, &#039; &#039;):gsub(&#039;del?&#039;, &#039;&#039;):gsub(&#039;&amp;amp;nbsp;&#039;, &#039; &#039;):gmatch(&#039;%S+&#039;) do&lt;br /&gt;
		item_count = item_count + 1&lt;br /&gt;
		if era_text[item] then&lt;br /&gt;
			-- Era is accepted in peculiar places.&lt;br /&gt;
			if options.era then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
			options.era = item&lt;br /&gt;
		elseif ampm_options[item] then&lt;br /&gt;
			if not set_ampm(item) then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
		elseif item:find(&#039;:&#039;, 1, true) then&lt;br /&gt;
			if not extract_time(item) then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
			index_time = item_count&lt;br /&gt;
		elseif date.day and date.month then&lt;br /&gt;
			if date.year then&lt;br /&gt;
				return  -- should be nothing more so item is invalid&lt;br /&gt;
			end&lt;br /&gt;
			if not item:match(&#039;^(%d%d?%d?%d?)$&#039;) then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
			date.year = tonumber(item)&lt;br /&gt;
		elseif day_number(item) then&lt;br /&gt;
		    --catch month day case&lt;br /&gt;
		elseif date.day then&lt;br /&gt;
			if not extract_month(item) then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
		elseif date.month then&lt;br /&gt;
			if not extract_day_or_year(item) then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
		elseif extract_month(item) then&lt;br /&gt;
			options.format = &#039;mdy&#039;&lt;br /&gt;
		elseif extract_ymd(item) then&lt;br /&gt;
			options.format = &#039;ymd&#039;&lt;br /&gt;
		elseif extract_day_or_year(item) then&lt;br /&gt;
			if date.day then&lt;br /&gt;
				options.format = &#039;dmy&#039;&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			--return  not return if item not recognized&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if not date.year or date.year == 0 then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	local era = era_text[options.era]&lt;br /&gt;
	if era and era.isbc then&lt;br /&gt;
		date.year = 1 - date.year&lt;br /&gt;
	end&lt;br /&gt;
	return date, options&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function autofill(date1, date2)&lt;br /&gt;
	-- Fill any missing month or day in each date using the&lt;br /&gt;
	-- corresponding component from the other date, if present,&lt;br /&gt;
	-- or with 1 if both dates are missing the month or day.&lt;br /&gt;
	-- This gives a good result for calculating the difference&lt;br /&gt;
	-- between two partial dates when no range is wanted.&lt;br /&gt;
	-- Return filled date1, date2 (two full dates).&lt;br /&gt;
	local function filled(a, b)&lt;br /&gt;
		local fillmonth, fillday&lt;br /&gt;
		if not a.month then&lt;br /&gt;
			fillmonth = b.month or 1&lt;br /&gt;
		end&lt;br /&gt;
		if not a.day then&lt;br /&gt;
			fillday = b.day or 1&lt;br /&gt;
		end&lt;br /&gt;
		if fillmonth or fillday then  -- need to create a new date&lt;br /&gt;
			if (fillmonth or a.month) == 2 and (fillday or a.day) == 29 then&lt;br /&gt;
				-- Avoid invalid date, for example with {{age|2013|29 Feb 2016}} or {{age|Feb 2013|29 Jan 2015}}.&lt;br /&gt;
				if not is_leap_year(a.year, a.calendar) then&lt;br /&gt;
					fillday = 28&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			a = Date(a, { month = fillmonth, day = fillday })&lt;br /&gt;
		end&lt;br /&gt;
		return a&lt;br /&gt;
	end&lt;br /&gt;
	return filled(date1, date2), filled(date2, date1)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function date_add_sub(lhs, rhs, is_sub)&lt;br /&gt;
	-- Return a new date from calculating (lhs + rhs) or (lhs - rhs),&lt;br /&gt;
	-- or return nothing if invalid.&lt;br /&gt;
	-- The result is nil if the calculated date exceeds allowable limits.&lt;br /&gt;
	-- Caller ensures that lhs is a date; its properties are copied for the new date.&lt;br /&gt;
	if lhs.partial then&lt;br /&gt;
		-- Adding to a partial is not supported.&lt;br /&gt;
		-- Can subtract a date or partial from a partial, but this is not called for that.&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	local function is_prefix(text, word, minlen)&lt;br /&gt;
		local n = #text&lt;br /&gt;
		return (minlen or 1) &amp;lt;= n and n &amp;lt;= #word and text == word:sub(1, n)&lt;br /&gt;
	end&lt;br /&gt;
	local function do_days(n)&lt;br /&gt;
		local forcetime, jd&lt;br /&gt;
		if floor(n) == n then&lt;br /&gt;
			jd = lhs.jd&lt;br /&gt;
		else&lt;br /&gt;
			forcetime = not lhs.hastime&lt;br /&gt;
			jd = lhs.jdz&lt;br /&gt;
		end&lt;br /&gt;
		jd = jd + (is_sub and -n or n)&lt;br /&gt;
		if forcetime then&lt;br /&gt;
			jd = tostring(jd)&lt;br /&gt;
			if not jd:find(&#039;.&#039;, 1, true) then&lt;br /&gt;
				jd = jd .. &#039;.0&#039;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return Date(lhs, &#039;juliandate&#039;, jd)&lt;br /&gt;
	end&lt;br /&gt;
	if type(rhs) == &#039;number&#039; then&lt;br /&gt;
		-- Add/subtract days, including fractional days.&lt;br /&gt;
		return do_days(rhs)&lt;br /&gt;
	end&lt;br /&gt;
	if type(rhs) == &#039;string&#039; then&lt;br /&gt;
		-- rhs is a single component like &#039;26m&#039; or &#039;26 months&#039; (with optional sign).&lt;br /&gt;
		-- Fractions like &#039;3.25d&#039; are accepted for the units which are handled as days.&lt;br /&gt;
		local sign, numstr, id = rhs:match(&#039;^%s*([+-]?)([%d%.]+)%s*(%a+)$&#039;)&lt;br /&gt;
		if sign then&lt;br /&gt;
			if sign == &#039;-&#039; then&lt;br /&gt;
				is_sub = not (is_sub and true or false)&lt;br /&gt;
			end&lt;br /&gt;
			local y, m, days&lt;br /&gt;
			local num = tonumber(numstr)&lt;br /&gt;
			if not num then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
			id = id:lower()&lt;br /&gt;
			if is_prefix(id, &#039;years&#039;) then&lt;br /&gt;
				y = num&lt;br /&gt;
				m = 0&lt;br /&gt;
			elseif is_prefix(id, &#039;months&#039;) then&lt;br /&gt;
				y = floor(num / 12)&lt;br /&gt;
				m = num % 12&lt;br /&gt;
			elseif is_prefix(id, &#039;weeks&#039;) then&lt;br /&gt;
				days = num * 7&lt;br /&gt;
			elseif is_prefix(id, &#039;days&#039;) then&lt;br /&gt;
				days = num&lt;br /&gt;
			elseif is_prefix(id, &#039;hours&#039;) then&lt;br /&gt;
				days = num / 24&lt;br /&gt;
			elseif is_prefix(id, &#039;minutes&#039;, 3) then&lt;br /&gt;
				days = num / (24 * 60)&lt;br /&gt;
			elseif is_prefix(id, &#039;seconds&#039;) then&lt;br /&gt;
				days = num / (24 * 3600)&lt;br /&gt;
			else&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
			if days then&lt;br /&gt;
				return do_days(days)&lt;br /&gt;
			end&lt;br /&gt;
			if numstr:find(&#039;.&#039;, 1, true) then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
			if is_sub then&lt;br /&gt;
				y = -y&lt;br /&gt;
				m = -m&lt;br /&gt;
			end&lt;br /&gt;
			assert(-11 &amp;lt;= m and m &amp;lt;= 11)&lt;br /&gt;
			y = lhs.year + y&lt;br /&gt;
			m = lhs.month + m&lt;br /&gt;
			if m &amp;gt; 12 then&lt;br /&gt;
				y = y + 1&lt;br /&gt;
				m = m - 12&lt;br /&gt;
			elseif m &amp;lt; 1 then&lt;br /&gt;
				y = y - 1&lt;br /&gt;
				m = m + 12&lt;br /&gt;
			end&lt;br /&gt;
			local d = math.min(lhs.day, days_in_month(y, m, lhs.calendar))&lt;br /&gt;
			return Date(lhs, y, m, d)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if is_diff(rhs) then&lt;br /&gt;
		local days = rhs.age_days&lt;br /&gt;
		if (is_sub or false) ~= (rhs.isnegative or false) then&lt;br /&gt;
			days = -days&lt;br /&gt;
		end&lt;br /&gt;
		return lhs + days&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local full_date_only = {&lt;br /&gt;
	dayabbr = true,&lt;br /&gt;
	dayname = true,&lt;br /&gt;
	dow = true,&lt;br /&gt;
	dayofweek = true,&lt;br /&gt;
	dowiso = true,&lt;br /&gt;
	dayofweekiso = true,&lt;br /&gt;
	dayofyear = true,&lt;br /&gt;
	gsd = true,&lt;br /&gt;
	juliandate = true,&lt;br /&gt;
	jd = true,&lt;br /&gt;
	jdz = true,&lt;br /&gt;
	jdnoon = true,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Metatable for a date&#039;s calculated fields.&lt;br /&gt;
local datemt = {&lt;br /&gt;
	__index = function (self, key)&lt;br /&gt;
		if rawget(self, &#039;partial&#039;) then&lt;br /&gt;
			if full_date_only[key] then return end&lt;br /&gt;
			if key == &#039;monthabbr&#039; or key == &#039;monthdays&#039; or key == &#039;monthname&#039; then&lt;br /&gt;
				if not self.month then return end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		local value&lt;br /&gt;
		if key == &#039;dayabbr&#039; then&lt;br /&gt;
			value = day_info[self.dow][1]&lt;br /&gt;
		elseif key == &#039;dayname&#039; then&lt;br /&gt;
			value = day_info[self.dow][2]&lt;br /&gt;
		elseif key == &#039;dow&#039; then&lt;br /&gt;
			value = (self.jdnoon + 1) % 7  -- day-of-week 0=Sun to 6=Sat&lt;br /&gt;
		elseif key == &#039;dayofweek&#039; then&lt;br /&gt;
			value = self.dow&lt;br /&gt;
		elseif key == &#039;dowiso&#039; then&lt;br /&gt;
			value = (self.jdnoon % 7) + 1  -- ISO day-of-week 1=Mon to 7=Sun&lt;br /&gt;
		elseif key == &#039;dayofweekiso&#039; then&lt;br /&gt;
			value = self.dowiso&lt;br /&gt;
		elseif key == &#039;dayofyear&#039; then&lt;br /&gt;
			local first = Date(self.year, 1, 1, self.calendar).jdnoon&lt;br /&gt;
			value = self.jdnoon - first + 1  -- day-of-year 1 to 366&lt;br /&gt;
		elseif key == &#039;era&#039; then&lt;br /&gt;
			-- Era text (never a negative sign) from year and options.&lt;br /&gt;
			value = get_era_for_year(self.options.era, self.year)&lt;br /&gt;
		elseif key == &#039;format&#039; then&lt;br /&gt;
			value = self.options.format or &#039;dmy&#039;&lt;br /&gt;
		elseif key == &#039;gsd&#039; then&lt;br /&gt;
			-- GSD = 1 from 00:00:00 to 23:59:59 on 1 January 1 AD Gregorian calendar,&lt;br /&gt;
			-- which is from jd 1721425.5 to 1721426.49999.&lt;br /&gt;
			value = floor(self.jd - 1721424.5)&lt;br /&gt;
		elseif key == &#039;juliandate&#039; or key == &#039;jd&#039; or key == &#039;jdz&#039; then&lt;br /&gt;
			local jd, jdz = julian_date(self)&lt;br /&gt;
			rawset(self, &#039;juliandate&#039;, jd)&lt;br /&gt;
			rawset(self, &#039;jd&#039;, jd)&lt;br /&gt;
			rawset(self, &#039;jdz&#039;, jdz)&lt;br /&gt;
			return key == &#039;jdz&#039; and jdz or jd&lt;br /&gt;
		elseif key == &#039;jdnoon&#039; then&lt;br /&gt;
			-- Julian date at noon (an integer) on the calendar day when jd occurs.&lt;br /&gt;
			value = floor(self.jd + 0.5)&lt;br /&gt;
		elseif key == &#039;isleapyear&#039; then&lt;br /&gt;
			value = is_leap_year(self.year, self.calendar)&lt;br /&gt;
		elseif key == &#039;monthabbr&#039; then&lt;br /&gt;
			value = month_info[self.month][1]&lt;br /&gt;
		elseif key == &#039;monthdays&#039; then&lt;br /&gt;
			value = days_in_month(self.year, self.month, self.calendar)&lt;br /&gt;
		elseif key == &#039;monthname&#039; then&lt;br /&gt;
			value = month_info[self.month][2]&lt;br /&gt;
		end&lt;br /&gt;
		if value ~= nil then&lt;br /&gt;
			rawset(self, key, value)&lt;br /&gt;
			return value&lt;br /&gt;
		end&lt;br /&gt;
	end,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Date operators.&lt;br /&gt;
local function mt_date_add(lhs, rhs)&lt;br /&gt;
	if not is_date(lhs) then&lt;br /&gt;
		lhs, rhs = rhs, lhs  -- put date on left (it must be a date for this to have been called)&lt;br /&gt;
	end&lt;br /&gt;
	return date_add_sub(lhs, rhs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function mt_date_sub(lhs, rhs)&lt;br /&gt;
	if is_date(lhs) then&lt;br /&gt;
		if is_date(rhs) then&lt;br /&gt;
			return DateDiff(lhs, rhs)&lt;br /&gt;
		end&lt;br /&gt;
		return date_add_sub(lhs, rhs, true)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function mt_date_concat(lhs, rhs)&lt;br /&gt;
	return tostring(lhs) .. tostring(rhs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function mt_date_tostring(self)&lt;br /&gt;
	return self:text()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function mt_date_eq(lhs, rhs)&lt;br /&gt;
	-- Return true if dates identify same date/time where, for example,&lt;br /&gt;
	-- Date(-4712, 1, 1, &#039;Julian&#039;) == Date(-4713, 11, 24, &#039;Gregorian&#039;) is true.&lt;br /&gt;
	-- This is called only if lhs and rhs have the same type and the same metamethod.&lt;br /&gt;
	if lhs.partial or rhs.partial then&lt;br /&gt;
		-- One date is partial; the other is a partial or a full date.&lt;br /&gt;
		-- The months may both be nil, but must be the same.&lt;br /&gt;
		return lhs.year == rhs.year and lhs.month == rhs.month and lhs.calendar == rhs.calendar&lt;br /&gt;
	end&lt;br /&gt;
	return lhs.jdz == rhs.jdz&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function mt_date_lt(lhs, rhs)&lt;br /&gt;
	-- Return true if lhs &amp;lt; rhs, for example,&lt;br /&gt;
	-- Date(&#039;1 Jan 2016&#039;) &amp;lt; Date(&#039;06:00 1 Jan 2016&#039;) is true.&lt;br /&gt;
	-- This is called only if lhs and rhs have the same type and the same metamethod.&lt;br /&gt;
	if lhs.partial or rhs.partial then&lt;br /&gt;
		-- One date is partial; the other is a partial or a full date.&lt;br /&gt;
		if lhs.calendar ~= rhs.calendar then&lt;br /&gt;
			return lhs.calendar == &#039;Julian&#039;&lt;br /&gt;
		end&lt;br /&gt;
		if lhs.partial then&lt;br /&gt;
			lhs = lhs.partial.first&lt;br /&gt;
		end&lt;br /&gt;
		if rhs.partial then&lt;br /&gt;
			rhs = rhs.partial.first&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return lhs.jdz &amp;lt; rhs.jdz&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[ Examples of syntax to construct a date:&lt;br /&gt;
Date(y, m, d, &#039;julian&#039;)             default calendar is &#039;gregorian&#039;&lt;br /&gt;
Date(y, m, d, H, M, S, &#039;julian&#039;)&lt;br /&gt;
Date(&#039;juliandate&#039;, jd, &#039;julian&#039;)    if jd contains &amp;quot;.&amp;quot; text output includes H:M:S&lt;br /&gt;
Date(&#039;currentdate&#039;)&lt;br /&gt;
Date(&#039;currentdatetime&#039;)&lt;br /&gt;
Date(&#039;1 April 1995&#039;, &#039;julian&#039;)      parse date from text&lt;br /&gt;
Date(&#039;1 April 1995 AD&#039;, &#039;julian&#039;)   using an era sets a flag to do the same for output&lt;br /&gt;
Date(&#039;04:30:59 1 April 1995&#039;, &#039;julian&#039;)&lt;br /&gt;
Date(date)                          copy of an existing date&lt;br /&gt;
Date(date, t)                       same, updated with y,m,d,H,M,S fields from table t&lt;br /&gt;
Date(t)                       		date with y,m,d,H,M,S fields from table t&lt;br /&gt;
]]&lt;br /&gt;
function Date(...)  -- for forward declaration above&lt;br /&gt;
	-- Return a table holding a date assuming a uniform calendar always applies&lt;br /&gt;
	-- (proleptic Gregorian calendar or proleptic Julian calendar), or&lt;br /&gt;
	-- return nothing if date is invalid.&lt;br /&gt;
	-- A partial date has a valid year, however its month may be nil, and&lt;br /&gt;
	-- its day and time fields are nil.&lt;br /&gt;
	-- Field partial is set to false (if a full date) or a table (if a partial date).&lt;br /&gt;
	local calendars = { julian = &#039;Julian&#039;, gregorian = &#039;Gregorian&#039; }&lt;br /&gt;
	local newdate = {&lt;br /&gt;
		_id = uniq,&lt;br /&gt;
		calendar = &#039;Gregorian&#039;,  -- default is Gregorian calendar&lt;br /&gt;
		hastime = false,  -- true if input sets a time&lt;br /&gt;
		hour = 0,  -- always set hour/minute/second so don&#039;t have to handle nil&lt;br /&gt;
		minute = 0,&lt;br /&gt;
		second = 0,&lt;br /&gt;
		options = {},&lt;br /&gt;
		list = _date_list,&lt;br /&gt;
		subtract = function (self, rhs, options)&lt;br /&gt;
			return DateDiff(self, rhs, options)&lt;br /&gt;
		end,&lt;br /&gt;
		text = _date_text,&lt;br /&gt;
	}&lt;br /&gt;
	local argtype, datetext, is_copy, jd_number, tnums&lt;br /&gt;
	local numindex = 0&lt;br /&gt;
	local numfields = { &#039;year&#039;, &#039;month&#039;, &#039;day&#039;, &#039;hour&#039;, &#039;minute&#039;, &#039;second&#039; }&lt;br /&gt;
	local numbers = {}&lt;br /&gt;
	for _, v in ipairs({...}) do&lt;br /&gt;
		v = strip_to_nil(v)&lt;br /&gt;
		local vlower = type(v) == &#039;string&#039; and v:lower() or nil&lt;br /&gt;
		if v == nil then&lt;br /&gt;
			-- Ignore empty arguments after stripping so modules can directly pass template parameters.&lt;br /&gt;
		elseif calendars[vlower] then&lt;br /&gt;
			newdate.calendar = calendars[vlower]&lt;br /&gt;
		elseif vlower == &#039;partial&#039; then&lt;br /&gt;
			newdate.partial = true&lt;br /&gt;
		elseif vlower == &#039;fix&#039; then&lt;br /&gt;
			newdate.want_fix = true&lt;br /&gt;
		elseif is_date(v) then&lt;br /&gt;
			-- Copy existing date (items can be overridden by other arguments).&lt;br /&gt;
			if is_copy or tnums then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
			is_copy = true&lt;br /&gt;
			newdate.calendar = v.calendar&lt;br /&gt;
			newdate.partial = v.partial&lt;br /&gt;
			newdate.hastime = v.hastime&lt;br /&gt;
			newdate.options = v.options&lt;br /&gt;
			newdate.year = v.year&lt;br /&gt;
			newdate.month = v.month&lt;br /&gt;
			newdate.day = v.day&lt;br /&gt;
			newdate.hour = v.hour&lt;br /&gt;
			newdate.minute = v.minute&lt;br /&gt;
			newdate.second = v.second&lt;br /&gt;
		elseif type(v) == &#039;table&#039; then&lt;br /&gt;
			if tnums then&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
			tnums = {}&lt;br /&gt;
			local tfields = { year=1, month=1, day=1, hour=2, minute=2, second=2 }&lt;br /&gt;
			for tk, tv in pairs(v) do&lt;br /&gt;
				if tfields[tk] then&lt;br /&gt;
					tnums[tk] = tonumber(tv)&lt;br /&gt;
				end&lt;br /&gt;
				if tfields[tk] == 2 then&lt;br /&gt;
					newdate.hastime = true&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			local num = tonumber(v)&lt;br /&gt;
			if not num and argtype == &#039;setdate&#039; and numindex == 1 then&lt;br /&gt;
				num = month_number(v)&lt;br /&gt;
			end&lt;br /&gt;
			if num then&lt;br /&gt;
				if not argtype then&lt;br /&gt;
					argtype = &#039;setdate&#039;&lt;br /&gt;
				end&lt;br /&gt;
				if argtype == &#039;setdate&#039; and numindex &amp;lt; 6 then&lt;br /&gt;
					numindex = numindex + 1&lt;br /&gt;
					numbers[numfields[numindex]] = num&lt;br /&gt;
				elseif argtype == &#039;juliandate&#039; and not jd_number then&lt;br /&gt;
					jd_number = num&lt;br /&gt;
					if type(v) == &#039;string&#039; then&lt;br /&gt;
						if v:find(&#039;.&#039;, 1, true) then&lt;br /&gt;
							newdate.hastime = true&lt;br /&gt;
						end&lt;br /&gt;
					elseif num ~= floor(num) then&lt;br /&gt;
						-- The given value was a number. The time will be used&lt;br /&gt;
						-- if the fractional part is nonzero.&lt;br /&gt;
						newdate.hastime = true&lt;br /&gt;
					end&lt;br /&gt;
				else&lt;br /&gt;
					return&lt;br /&gt;
				end&lt;br /&gt;
			elseif argtype then&lt;br /&gt;
				return&lt;br /&gt;
			elseif type(v) == &#039;string&#039; then&lt;br /&gt;
				if v == &#039;currentdate&#039; or v == &#039;currentdatetime&#039; or v == &#039;juliandate&#039; then&lt;br /&gt;
					argtype = v&lt;br /&gt;
				else&lt;br /&gt;
					argtype = &#039;datetext&#039;&lt;br /&gt;
					datetext = v&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				return&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if argtype == &#039;datetext&#039; then&lt;br /&gt;
		if tnums or not set_date_from_numbers(newdate, extract_date(newdate, datetext)) then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
	elseif argtype == &#039;juliandate&#039; then&lt;br /&gt;
		newdate.partial = nil&lt;br /&gt;
		newdate.jd = jd_number&lt;br /&gt;
		if not set_date_from_jd(newdate) then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
	elseif argtype == &#039;currentdate&#039; or argtype == &#039;currentdatetime&#039; then&lt;br /&gt;
		newdate.partial = nil&lt;br /&gt;
		newdate.year = current.year&lt;br /&gt;
		newdate.month = current.month&lt;br /&gt;
		newdate.day = current.day&lt;br /&gt;
		if argtype == &#039;currentdatetime&#039; then&lt;br /&gt;
			newdate.hour = current.hour&lt;br /&gt;
			newdate.minute = current.minute&lt;br /&gt;
			newdate.second = current.second&lt;br /&gt;
			newdate.hastime = true&lt;br /&gt;
		end&lt;br /&gt;
		newdate.calendar = &#039;Gregorian&#039;  -- ignore any given calendar name&lt;br /&gt;
	elseif argtype == &#039;setdate&#039; then&lt;br /&gt;
		if tnums or not set_date_from_numbers(newdate, numbers) then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
	elseif not (is_copy or tnums) then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	if tnums then&lt;br /&gt;
		newdate.jd = nil  -- force recalculation in case jd was set before changes from tnums&lt;br /&gt;
		if not set_date_from_numbers(newdate, tnums) then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if newdate.partial then&lt;br /&gt;
		local year = newdate.year&lt;br /&gt;
		local month = newdate.month&lt;br /&gt;
		local first = Date(year, month or 1, 1, newdate.calendar)&lt;br /&gt;
		month = month or 12&lt;br /&gt;
		local last = Date(year, month, days_in_month(year, month), newdate.calendar)&lt;br /&gt;
		newdate.partial = { first = first, last = last }&lt;br /&gt;
	else&lt;br /&gt;
		newdate.partial = false  -- avoid index lookup&lt;br /&gt;
	end&lt;br /&gt;
	setmetatable(newdate, datemt)&lt;br /&gt;
	local readonly = {}&lt;br /&gt;
	local mt = {&lt;br /&gt;
		__index = newdate,&lt;br /&gt;
		__newindex = function(t, k, v) error(&#039;date.&#039; .. tostring(k) .. &#039; is read-only&#039;, 2) end,&lt;br /&gt;
		__add = mt_date_add,&lt;br /&gt;
		__sub = mt_date_sub,&lt;br /&gt;
		__concat = mt_date_concat,&lt;br /&gt;
		__tostring = mt_date_tostring,&lt;br /&gt;
		__eq = mt_date_eq,&lt;br /&gt;
		__lt = mt_date_lt,&lt;br /&gt;
	}&lt;br /&gt;
	return setmetatable(readonly, mt)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function _diff_age(diff, code, options)&lt;br /&gt;
	-- Return a tuple of integer values from diff as specified by code, except that&lt;br /&gt;
	-- each integer may be a list of two integers for a diff with a partial date, or&lt;br /&gt;
	-- return nil if the code is not supported.&lt;br /&gt;
	-- If want round, the least significant unit is rounded to nearest whole unit.&lt;br /&gt;
	-- For a duration, an extra day is added.&lt;br /&gt;
	local wantround, wantduration, wantrange&lt;br /&gt;
	if type(options) == &#039;table&#039; then&lt;br /&gt;
		wantround = options.round&lt;br /&gt;
		wantduration = options.duration&lt;br /&gt;
		wantrange = options.range&lt;br /&gt;
	else&lt;br /&gt;
		wantround = options&lt;br /&gt;
	end&lt;br /&gt;
	if not is_diff(diff) then&lt;br /&gt;
		local f = wantduration and &#039;duration&#039; or &#039;age&#039;&lt;br /&gt;
		error(f .. &#039;: need a date difference (use &amp;quot;diff:&#039; .. f .. &#039;()&amp;quot; with a colon)&#039;, 2)&lt;br /&gt;
	end&lt;br /&gt;
	if diff.partial then&lt;br /&gt;
		-- Ignore wantround, wantduration.&lt;br /&gt;
		local function choose(v)&lt;br /&gt;
			if type(v) == &#039;table&#039; then&lt;br /&gt;
				if not wantrange or v[1] == v[2] then&lt;br /&gt;
					-- Example: Date(&#039;partial&#039;, 2005) - Date(&#039;partial&#039;, 2001) gives&lt;br /&gt;
					-- diff.years = { 3, 4 } to show the range of possible results.&lt;br /&gt;
					-- If do not want a range, choose the second value as more expected.&lt;br /&gt;
					return v[2]&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			return v&lt;br /&gt;
		end&lt;br /&gt;
		if code == &#039;ym&#039; or code == &#039;ymd&#039; then&lt;br /&gt;
			if not wantrange and diff.iszero then&lt;br /&gt;
				-- This avoids an unexpected result such as&lt;br /&gt;
				-- Date(&#039;partial&#039;, 2001) - Date(&#039;partial&#039;, 2001)&lt;br /&gt;
				-- giving diff = { years = 0, months = { 0, 11 } }&lt;br /&gt;
				-- which would be reported as 0 years and 11 months.&lt;br /&gt;
				return 0, 0&lt;br /&gt;
			end&lt;br /&gt;
			return choose(diff.partial.years), choose(diff.partial.months)&lt;br /&gt;
		end&lt;br /&gt;
		if code == &#039;y&#039; then&lt;br /&gt;
			return choose(diff.partial.years)&lt;br /&gt;
		end&lt;br /&gt;
		if code == &#039;m&#039; or code == &#039;w&#039; or code == &#039;d&#039; then&lt;br /&gt;
			return choose({ diff.partial.mindiff:age(code), diff.partial.maxdiff:age(code) })&lt;br /&gt;
		end&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local extra_days = wantduration and 1 or 0&lt;br /&gt;
	if code == &#039;wd&#039; or code == &#039;w&#039; or code == &#039;d&#039; then&lt;br /&gt;
		local offset = wantround and 0.5 or 0&lt;br /&gt;
		local days = diff.age_days + extra_days&lt;br /&gt;
		if code == &#039;wd&#039; or code == &#039;d&#039; then&lt;br /&gt;
			days = floor(days + offset)&lt;br /&gt;
			if code == &#039;d&#039; then&lt;br /&gt;
				return days&lt;br /&gt;
			end&lt;br /&gt;
			return floor(days/7), days % 7&lt;br /&gt;
		end&lt;br /&gt;
		return floor(days/7 + offset)&lt;br /&gt;
	end&lt;br /&gt;
	local H, M, S = diff.hours, diff.minutes, diff.seconds&lt;br /&gt;
	if code == &#039;dh&#039; or code == &#039;dhm&#039; or code == &#039;dhms&#039; or code == &#039;h&#039; or code == &#039;hm&#039; or code == &#039;hms&#039; then&lt;br /&gt;
		local days = floor(diff.age_days + extra_days)&lt;br /&gt;
		local inc_hour&lt;br /&gt;
		if wantround then&lt;br /&gt;
			if code == &#039;dh&#039; or code == &#039;h&#039; then&lt;br /&gt;
				if M &amp;gt;= 30 then&lt;br /&gt;
					inc_hour = true&lt;br /&gt;
				end&lt;br /&gt;
			elseif code == &#039;dhm&#039; or code == &#039;hm&#039; then&lt;br /&gt;
				if S &amp;gt;= 30 then&lt;br /&gt;
					M = M + 1&lt;br /&gt;
					if M &amp;gt;= 60 then&lt;br /&gt;
						M = 0&lt;br /&gt;
						inc_hour = true&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				-- Nothing needed because S is an integer.&lt;br /&gt;
			end&lt;br /&gt;
			if inc_hour then&lt;br /&gt;
				H = H + 1&lt;br /&gt;
				if H &amp;gt;= 24 then&lt;br /&gt;
					H = 0&lt;br /&gt;
					days = days + 1&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if code == &#039;dh&#039; or code == &#039;dhm&#039; or code == &#039;dhms&#039; then&lt;br /&gt;
			if code == &#039;dh&#039; then&lt;br /&gt;
				return days, H&lt;br /&gt;
			elseif code == &#039;dhm&#039; then&lt;br /&gt;
				return days, H, M&lt;br /&gt;
			else&lt;br /&gt;
				return days, H, M, S&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		local hours = days * 24 + H&lt;br /&gt;
		if code == &#039;h&#039; then&lt;br /&gt;
			return hours&lt;br /&gt;
		elseif code == &#039;hm&#039; then&lt;br /&gt;
			return hours, M&lt;br /&gt;
		end&lt;br /&gt;
		return hours, M, S&lt;br /&gt;
	end&lt;br /&gt;
	if wantround then&lt;br /&gt;
		local inc_hour&lt;br /&gt;
		if code == &#039;ymdh&#039; or code == &#039;ymwdh&#039; then&lt;br /&gt;
			if M &amp;gt;= 30 then&lt;br /&gt;
				inc_hour = true&lt;br /&gt;
			end&lt;br /&gt;
		elseif code == &#039;ymdhm&#039; or code == &#039;ymwdhm&#039; then&lt;br /&gt;
			if S &amp;gt;= 30 then&lt;br /&gt;
				M = M + 1&lt;br /&gt;
				if M &amp;gt;= 60 then&lt;br /&gt;
					M = 0&lt;br /&gt;
					inc_hour = true&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		elseif code == &#039;ymd&#039; or code == &#039;ymwd&#039; or code == &#039;yd&#039; or code == &#039;md&#039; then&lt;br /&gt;
			if H &amp;gt;= 12 then&lt;br /&gt;
				extra_days = extra_days + 1&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if inc_hour then&lt;br /&gt;
			H = H + 1&lt;br /&gt;
			if H &amp;gt;= 24 then&lt;br /&gt;
				H = 0&lt;br /&gt;
				extra_days = extra_days + 1&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local y, m, d = diff.years, diff.months, diff.days&lt;br /&gt;
	if extra_days &amp;gt; 0 then&lt;br /&gt;
		d = d + extra_days&lt;br /&gt;
		if d &amp;gt; 28 or code == &#039;yd&#039; then&lt;br /&gt;
			-- Recalculate in case have passed a month.&lt;br /&gt;
			diff = diff.date1 + extra_days - diff.date2&lt;br /&gt;
			y, m, d = diff.years, diff.months, diff.days&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if code == &#039;ymd&#039; then&lt;br /&gt;
		return y, m, d&lt;br /&gt;
	elseif code == &#039;yd&#039; then&lt;br /&gt;
		if y &amp;gt; 0 then&lt;br /&gt;
			-- It is known that diff.date1 &amp;gt; diff.date2.&lt;br /&gt;
			diff = diff.date1 - (diff.date2 + (y .. &#039;y&#039;))&lt;br /&gt;
		end&lt;br /&gt;
		return y, floor(diff.age_days)&lt;br /&gt;
	elseif code == &#039;md&#039; then&lt;br /&gt;
		return y * 12 + m, d&lt;br /&gt;
	elseif code == &#039;ym&#039; or code == &#039;m&#039; then&lt;br /&gt;
		if wantround then&lt;br /&gt;
			if d &amp;gt;= 16 then&lt;br /&gt;
				m = m + 1&lt;br /&gt;
				if m &amp;gt;= 12 then&lt;br /&gt;
					m = 0&lt;br /&gt;
					y = y + 1&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if code == &#039;ym&#039; then&lt;br /&gt;
			return y, m&lt;br /&gt;
		end&lt;br /&gt;
		return y * 12 + m&lt;br /&gt;
	elseif code == &#039;ymw&#039; then&lt;br /&gt;
		local weeks = floor(d/7)&lt;br /&gt;
		if wantround then&lt;br /&gt;
			local days = d % 7&lt;br /&gt;
			if days &amp;gt; 3 or (days == 3 and H &amp;gt;= 12) then&lt;br /&gt;
				weeks = weeks + 1&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return y, m, weeks&lt;br /&gt;
	elseif code == &#039;ymwd&#039; then&lt;br /&gt;
		return y, m, floor(d/7), d % 7&lt;br /&gt;
	elseif code == &#039;ymdh&#039; then&lt;br /&gt;
		return y, m, d, H&lt;br /&gt;
	elseif code == &#039;ymwdh&#039; then&lt;br /&gt;
		return y, m, floor(d/7), d % 7, H&lt;br /&gt;
	elseif code == &#039;ymdhm&#039; then&lt;br /&gt;
		return y, m, d, H, M&lt;br /&gt;
	elseif code == &#039;ymwdhm&#039; then&lt;br /&gt;
		return y, m, floor(d/7), d % 7, H, M&lt;br /&gt;
	end&lt;br /&gt;
	if code == &#039;y&#039; then&lt;br /&gt;
		if wantround and m &amp;gt;= 6 then&lt;br /&gt;
			y = y + 1&lt;br /&gt;
		end&lt;br /&gt;
		return y&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function _diff_duration(diff, code, options)&lt;br /&gt;
	if type(options) ~= &#039;table&#039; then&lt;br /&gt;
		options = { round = options }&lt;br /&gt;
	end&lt;br /&gt;
	options.duration = true&lt;br /&gt;
	return _diff_age(diff, code, options)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Metatable for some operations on date differences.&lt;br /&gt;
diffmt = {  -- for forward declaration above&lt;br /&gt;
	__concat = function (lhs, rhs)&lt;br /&gt;
		return tostring(lhs) .. tostring(rhs)&lt;br /&gt;
	end,&lt;br /&gt;
	__tostring = function (self)&lt;br /&gt;
		return tostring(self.age_days)&lt;br /&gt;
	end,&lt;br /&gt;
	__index = function (self, key)&lt;br /&gt;
		local value&lt;br /&gt;
		if key == &#039;age_days&#039; then&lt;br /&gt;
			if rawget(self, &#039;partial&#039;) then&lt;br /&gt;
				local function jdz(date)&lt;br /&gt;
					return (date.partial and date.partial.first or date).jdz&lt;br /&gt;
				end&lt;br /&gt;
				value = jdz(self.date1) - jdz(self.date2)&lt;br /&gt;
			else&lt;br /&gt;
				value = self.date1.jdz - self.date2.jdz&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if value ~= nil then&lt;br /&gt;
			rawset(self, key, value)&lt;br /&gt;
			return value&lt;br /&gt;
		end&lt;br /&gt;
	end,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function DateDiff(date1, date2, options)  -- for forward declaration above&lt;br /&gt;
	-- Return a table with the difference between two dates (date1 - date2).&lt;br /&gt;
	-- The difference is negative if date1 is older than date2.&lt;br /&gt;
	-- Return nothing if invalid.&lt;br /&gt;
	-- If d = date1 - date2 then&lt;br /&gt;
	--     date1 = date2 + d&lt;br /&gt;
	-- If date1 &amp;gt;= date2 and the dates have no H:M:S time specified then&lt;br /&gt;
	--     date1 = date2 + (d.years..&#039;y&#039;) + (d.months..&#039;m&#039;) + d.days&lt;br /&gt;
	-- where the larger time units are added first.&lt;br /&gt;
	-- The result of Date(2015,1,x) + &#039;1m&#039; is Date(2015,2,28) for&lt;br /&gt;
	-- x = 28, 29, 30, 31. That means, for example,&lt;br /&gt;
	--     d = Date(2015,3,3) - Date(2015,1,31)&lt;br /&gt;
	-- gives d.years, d.months, d.days = 0, 1, 3 (excluding date1).&lt;br /&gt;
	if not (is_date(date1) and is_date(date2) and date1.calendar == date2.calendar) then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	local wantfill&lt;br /&gt;
	if type(options) == &#039;table&#039; then&lt;br /&gt;
		wantfill = options.fill&lt;br /&gt;
	end&lt;br /&gt;
	local isnegative = false&lt;br /&gt;
	local iszero = false&lt;br /&gt;
	if date1 &amp;lt; date2 then&lt;br /&gt;
		isnegative = true&lt;br /&gt;
		date1, date2 = date2, date1&lt;br /&gt;
	elseif date1 == date2 then&lt;br /&gt;
		iszero = true&lt;br /&gt;
	end&lt;br /&gt;
	-- It is known that date1 &amp;gt;= date2 (period is from date2 to date1).&lt;br /&gt;
	if date1.partial or date2.partial then&lt;br /&gt;
		-- Two partial dates might have timelines:&lt;br /&gt;
		---------------------A=================B--- date1 is from A to B inclusive&lt;br /&gt;
		--------C=======D-------------------------- date2 is from C to D inclusive&lt;br /&gt;
		-- date1 &amp;gt; date2 iff A &amp;gt; C (date1.partial.first &amp;gt; date2.partial.first)&lt;br /&gt;
		-- The periods can overlap (&#039;April 2001&#039; - &#039;2001&#039;):&lt;br /&gt;
		-------------A===B------------------------- A=2001-04-01  B=2001-04-30&lt;br /&gt;
		--------C=====================D------------ C=2001-01-01  D=2001-12-31&lt;br /&gt;
		if wantfill then&lt;br /&gt;
			date1, date2 = autofill(date1, date2)&lt;br /&gt;
		else&lt;br /&gt;
			local function zdiff(date1, date2)&lt;br /&gt;
				local diff = date1 - date2&lt;br /&gt;
				if diff.isnegative then&lt;br /&gt;
					return date1 - date1  -- a valid diff in case we call its methods&lt;br /&gt;
				end&lt;br /&gt;
				return diff&lt;br /&gt;
			end&lt;br /&gt;
			local function getdate(date, which)&lt;br /&gt;
				return date.partial and date.partial[which] or date&lt;br /&gt;
			end&lt;br /&gt;
			local maxdiff = zdiff(getdate(date1, &#039;last&#039;), getdate(date2, &#039;first&#039;))&lt;br /&gt;
			local mindiff = zdiff(getdate(date1, &#039;first&#039;), getdate(date2, &#039;last&#039;))&lt;br /&gt;
			local years, months&lt;br /&gt;
			if maxdiff.years == mindiff.years then&lt;br /&gt;
				years = maxdiff.years&lt;br /&gt;
				if maxdiff.months == mindiff.months then&lt;br /&gt;
					months = maxdiff.months&lt;br /&gt;
				else&lt;br /&gt;
					months = { mindiff.months, maxdiff.months }&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				years = { mindiff.years, maxdiff.years }&lt;br /&gt;
			end&lt;br /&gt;
			return setmetatable({&lt;br /&gt;
				date1 = date1,&lt;br /&gt;
				date2 = date2,&lt;br /&gt;
				partial = {&lt;br /&gt;
					years = years,&lt;br /&gt;
					months = months,&lt;br /&gt;
					maxdiff = maxdiff,&lt;br /&gt;
					mindiff = mindiff,&lt;br /&gt;
				},&lt;br /&gt;
				isnegative = isnegative,&lt;br /&gt;
				iszero = iszero,&lt;br /&gt;
				age = _diff_age,&lt;br /&gt;
				duration = _diff_duration,&lt;br /&gt;
			}, diffmt)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local y1, m1 = date1.year, date1.month&lt;br /&gt;
	local y2, m2 = date2.year, date2.month&lt;br /&gt;
	local years = y1 - y2&lt;br /&gt;
	local months = m1 - m2&lt;br /&gt;
	local d1 = date1.day + hms(date1)&lt;br /&gt;
	local d2 = date2.day + hms(date2)&lt;br /&gt;
	local days, time&lt;br /&gt;
	if d1 &amp;gt;= d2 then&lt;br /&gt;
		days = d1 - d2&lt;br /&gt;
	else&lt;br /&gt;
		months = months - 1&lt;br /&gt;
		-- Get days in previous month (before the &amp;quot;to&amp;quot; date) given December has 31 days.&lt;br /&gt;
		local dpm = m1 &amp;gt; 1 and days_in_month(y1, m1 - 1, date1.calendar) or 31&lt;br /&gt;
		if d2 &amp;gt;= dpm then&lt;br /&gt;
			days = d1 - hms(date2)&lt;br /&gt;
		else&lt;br /&gt;
			days = dpm - d2 + d1&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if months &amp;lt; 0 then&lt;br /&gt;
		years = years - 1&lt;br /&gt;
		months = months + 12&lt;br /&gt;
	end&lt;br /&gt;
	days, time = math.modf(days)&lt;br /&gt;
	local H, M, S = h_m_s(time)&lt;br /&gt;
	return setmetatable({&lt;br /&gt;
		date1 = date1,&lt;br /&gt;
		date2 = date2,&lt;br /&gt;
		partial = false,  -- avoid index lookup&lt;br /&gt;
		years = years,&lt;br /&gt;
		months = months,&lt;br /&gt;
		days = days,&lt;br /&gt;
		hours = H,&lt;br /&gt;
		minutes = M,&lt;br /&gt;
		seconds = S,&lt;br /&gt;
		isnegative = isnegative,&lt;br /&gt;
		iszero = iszero,&lt;br /&gt;
		age = _diff_age,&lt;br /&gt;
		duration = _diff_duration,&lt;br /&gt;
	}, diffmt)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local z = {&lt;br /&gt;
	_current = current,&lt;br /&gt;
	_Date = Date,&lt;br /&gt;
	_days_in_month = days_in_month,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- Aqui comienzas las funciones adaptadas de [[Módulo:Fecha]] --&lt;br /&gt;
----------------------------------------------------------------&lt;br /&gt;
----------------------------------------------------------------&lt;br /&gt;
----------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function z.fechaActual()&lt;br /&gt;
	local d = os.date(&#039;!*t&#039;)&lt;br /&gt;
	&lt;br /&gt;
	local fecha = {}&lt;br /&gt;
	fecha.anyo    = d.year&lt;br /&gt;
	fecha.mes     = d.month&lt;br /&gt;
	fecha.dia     = d.day&lt;br /&gt;
	fecha.hora    = d.hour&lt;br /&gt;
	fecha.minuto  = d.min&lt;br /&gt;
	fecha.segundo = d.sec&lt;br /&gt;
		&lt;br /&gt;
	return fecha&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function validar(fecha)&lt;br /&gt;
	fecha.anyo    = tonumber(fecha.anyo)&lt;br /&gt;
	fecha.mes     = tonumber(fecha.mes)&lt;br /&gt;
	fecha.dia     = tonumber(fecha.dia)&lt;br /&gt;
	fecha.hora    = tonumber(fecha.hora)&lt;br /&gt;
	fecha.minuto  = tonumber(fecha.minuto)&lt;br /&gt;
	fecha.segundo = tonumber(fecha.segundo)&lt;br /&gt;
	&lt;br /&gt;
	-- Falta validar que es una fecha válida&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function z.edad(fecha1, fecha2)&lt;br /&gt;
	--Función que devuelve la edad en años entre dos fechas&lt;br /&gt;
	&lt;br /&gt;
	--Se supone que las fechas se han validado previamente.&lt;br /&gt;
	&lt;br /&gt;
	if not fecha1 then&lt;br /&gt;
		return -- falta devolver un error&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if not fecha2 then&lt;br /&gt;
		fecha2=z.fechaActual()&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local anyos = fecha2.anyo - fecha1.anyo&lt;br /&gt;
	&lt;br /&gt;
	--if true then return require(&#039;Módulo:Tablas&#039;).tostring(fecha2) end&lt;br /&gt;
	&lt;br /&gt;
	if fecha2.mes &amp;lt; fecha1.mes or&lt;br /&gt;
	   (fecha2.mes == fecha1.mes and fecha2.dia &amp;lt; fecha1.dia) then&lt;br /&gt;
	   	anyos = anyos - 1&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if anyos &amp;lt; 0 then&lt;br /&gt;
		return -- falta devolver error&lt;br /&gt;
	elseif anyos == 0 then&lt;br /&gt;
		return &#039;menos de un año&#039;&lt;br /&gt;
	elseif anyos == 1 then&lt;br /&gt;
		return &#039;un año&#039;&lt;br /&gt;
	else&lt;br /&gt;
		return anyos .. &#039; años&#039;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function z.llamadaDesdeUnaPlantilla(frame)&lt;br /&gt;
	function obtenerFecha(dia, mes, anyo)&lt;br /&gt;
		local resultado={}&lt;br /&gt;
	&lt;br /&gt;
		if dia then&lt;br /&gt;
			resultado.dia  = dia&lt;br /&gt;
			resultado.mes  = mes&lt;br /&gt;
			resultado.anyo = anyo&lt;br /&gt;
			&lt;br /&gt;
			validar(resultado)&lt;br /&gt;
			&lt;br /&gt;
			return resultado&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	&lt;br /&gt;
	local funcion = z[args[1]]&lt;br /&gt;
	local fecha1  = obtenerFecha(args[2], args[3], args[4])&lt;br /&gt;
	local fecha2  = obtenerFecha(args[5], args[6], args[7])&lt;br /&gt;
&lt;br /&gt;
	return funcion(fecha1, fecha2)&lt;br /&gt;
end&lt;br /&gt;
       &lt;br /&gt;
&lt;br /&gt;
-- Aqui comienzas las funciones adaptadas de [[Módulo:Fechas]] --&lt;br /&gt;
-----------------------------------------------------------------&lt;br /&gt;
-----------------------------------------------------------------&lt;br /&gt;
-----------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function z.NombreDelMes(mes)&lt;br /&gt;
  -- Función que devuelve el nombre del mes, donde mes es un número entre 1 y 12. &lt;br /&gt;
  -- Si no es así se devuelve el valor de mes.&lt;br /&gt;
  -- Por ejemplo, 2  --&amp;gt; febrero&lt;br /&gt;
  --              02 --&amp;gt; febrero&lt;br /&gt;
  --              abril --&amp;gt; abril&lt;br /&gt;
  --              MAYO --&amp;gt; MAYO&lt;br /&gt;
   return month_info[tonumber(mes)][2] or mes&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function z.Fecha(frame)&lt;br /&gt;
    -- Función que formatea una fecha&lt;br /&gt;
    -- El único parámetro obligatorio es el año o 3.&lt;br /&gt;
    -- Obtener los argumentos con los que se llama a la función&lt;br /&gt;
&lt;br /&gt;
    local argumentos = {}&lt;br /&gt;
    local parent = {}&lt;br /&gt;
    if frame == mw.getCurrentFrame() then&lt;br /&gt;
        if   frame.args[3]  or frame.args[&amp;quot;año&amp;quot;]  then&lt;br /&gt;
    	    argumentos = frame.args&lt;br /&gt;
        else &lt;br /&gt;
    	    parent = frame:getParent()&lt;br /&gt;
            argumentos = parent.args&lt;br /&gt;
        end &lt;br /&gt;
    else&lt;br /&gt;
        argumentos = frame&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local enlace = argumentos[&amp;quot;enlace&amp;quot;] ~= &amp;quot;no&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    -- Obtener el día, el nombre del mes y el año incluyendo para los años negativos a.d.&lt;br /&gt;
    local dia = argumentos[&amp;quot;día&amp;quot;] or argumentos[1] or &#039;&#039;    &lt;br /&gt;
    local mes = argumentos[&amp;quot;mes&amp;quot;] or argumentos[2] or &#039;&#039; &lt;br /&gt;
    local anyo=tonumber(argumentos[&amp;quot;año&amp;quot;] or argumentos[3]) or 0&lt;br /&gt;
	&lt;br /&gt;
    dia = (dia ~=&#039;&#039;) and (tonumber(dia) or dia) or dia -- Eliminar ceros a la izquierda del día.&lt;br /&gt;
    mes = (mes~=&#039;&#039;) and ((month_info[mes] and month_info[mes][2]) or month_info[tonumber(mes)][2] or mes) or mes -- Extraer nombre del mes&lt;br /&gt;
    anyo = (anyo&amp;lt;0) and (-anyo .. &#039; a. C.&#039;) or anyo&lt;br /&gt;
    &lt;br /&gt;
    local calendario = (argumentos[&amp;quot;calendario&amp;quot;] == &#039;juliano&#039;) and (&#039;&amp;lt;sup&amp;gt;[[Calendario juliano|jul.]]&amp;lt;/sup&amp;gt;&#039;) or &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    -- Formatear la fecha dependiendo de si el día, el mes o el año están informados&lt;br /&gt;
	local out = &#039;&#039;&lt;br /&gt;
	&lt;br /&gt;
	if anyo ~= 0 then&lt;br /&gt;
		out = enlace and (out .. &#039;[[&#039; .. anyo .. &#039;]]&#039;) or tostring(anyo)&lt;br /&gt;
		if mes~=&#039;&#039; then&lt;br /&gt;
			if argumentos[&amp;quot;mayúscula&amp;quot;] == &#039;sí&#039; then&lt;br /&gt;
				mes = mw.language.new(&#039;es&#039;):ucfirst(mes)&lt;br /&gt;
			end&lt;br /&gt;
			out = enlace and (mes .. &#039;]] de &#039; .. out) or (mes .. &#039; de &#039; .. out)&lt;br /&gt;
			if dia ~=&#039;&#039; then&lt;br /&gt;
				out = enlace and (&#039;[[&#039; .. dia .. &#039; de &#039; .. out .. calendario) or (dia .. &#039; de &#039; .. out .. calendario)&lt;br /&gt;
			else&lt;br /&gt;
				out = enlace and (&#039;[[&#039; .. out) or out&lt;br /&gt;
			end	&lt;br /&gt;
		end&lt;br /&gt;
	 end&lt;br /&gt;
	return out&lt;br /&gt;
 end&lt;br /&gt;
 &lt;br /&gt;
 function z.Numerica(frame)&lt;br /&gt;
	local d = Date(frame.args[1])&lt;br /&gt;
    local err = &#039;&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;Cadena de fecha no válida&amp;lt;/strong&amp;gt;&#039;&lt;br /&gt;
	return (d == nil) and err or d:text(&#039;%Y%m%d&#039;)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
return z&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:Changetitle&amp;diff=5415</id>
		<title>Plantilla:Changetitle</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:Changetitle&amp;diff=5415"/>
		<updated>2022-11-27T02:38:40Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Plantilla:Título]]&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:Center&amp;diff=5413</id>
		<title>Plantilla:Center</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:Center&amp;diff=5413"/>
		<updated>2022-11-27T02:38:40Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECCIÓN [[Plantilla:Centrar]]&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:Br_separated_entries&amp;diff=5411</id>
		<title>Plantilla:Br separated entries</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:Br_separated_entries&amp;diff=5411"/>
		<updated>2022-11-27T02:38:40Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:Separated entries|br}}&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
	<entry>
		<id>https://es.prole.wiki/w/index.php?title=Plantilla:Align&amp;diff=5409</id>
		<title>Plantilla:Align</title>
		<link rel="alternate" type="text/html" href="https://es.prole.wiki/w/index.php?title=Plantilla:Align&amp;diff=5409"/>
		<updated>2022-11-27T02:38:40Z</updated>

		<summary type="html">&lt;p&gt;ProleWiki: 1 revisión importada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#switch: {{lc:{{{1|center}}}}}&lt;br /&gt;
|left = &amp;lt;div style=&amp;quot;float: left;&amp;quot;&amp;gt;{{{2}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
|right = &amp;lt;div style=&amp;quot;float: right;&amp;quot;&amp;gt;{{{2}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
|center = {{center|{{{2}}} }}&lt;br /&gt;
|#default = Error en  la [Plantilla:Align]]: el parámetro de alineamiento &amp;quot;{{{1}}}&amp;quot; es invalido.&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentación}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>ProleWiki</name></author>
	</entry>
</feed>