Documentation[créer] [purger]
--[[
  ce module a pour but − uniquement pour fr: − d'émuler les fonctions retournant
  la date et heure sous diverses formes.
  Il s'agit des pseudo-modèles {{CURRENTYEAR}}, {{CURRENTHOUR}}…
  Utilise l'heure UTC + 1h, car c'est l'heure utilisée sur fr:
--]]

local p = {}

--- fonctions pour traiter les mises en format spécifiques
-- passage format %02d → %d
function p.ft_2_1(valeur, opt)
    return tonumber(valeur) or "err"
end
-- passage format %d → %02d
function p.ft_1_2(valeur, opt)
    if (opt == nil or opt == "") then
        return mw.ustring.format("%02d", valeur) or "err"
    else
        return mw.ustring.format("%0" .. opt .. "d", valeur) or "err"
    end
end

-- liste des codes et clé d'accès date
-- format :
--  [mot-clé] = { "code date", fonction à appliquer, nil }
-- si fonction ~= nil alors la valeur retournée est fonction(retour-code-date)
-- le dernier paramètre dépend de la fonction
p.access = {
    ["YEAR"] = {"Y",nil,nil, "Année sur 4 chiffres"}, ["MONTH"] = {"m",nil,nil, "Mois sur 2 chiffres (01-12)"},
    ["MONTH2"] = {"m",nil,nil, "Mois sur 2 chiffres (01-12)"}, ["MONTH1"] = {"n",nil,nil, "Mois sur 1 ou 2 chiffres (1-12)"},
    ["MONTHNAME"] = {"F",nil,nil, "Nom du mois"}, ["MONTHABBREV"] = {"M",nil,nil, "Nom abrégé du mois"},
    ["WEEK"] = {"W", nil,nil, "Numéro de la semaine (ISO8601) sur 2 chiffres"},
    ["WEEK2"] = {"W", nil,nil, "Numéro de la semaine (ISO8601) sur 2 chiffres"},
    ["WEEK1"] = {"W", p.ft_2_1,nil, "Numéro de la semaine (ISO8601) sur 1 ou 2 chiffres"},
    ["DAY"] = {"j",nil,nil, "Numéro du jour du mois sur 1 ou 2 chiffres"}, ["DAY1"] = {"j",nil,nil, "Numéro du jour du mois sur 1 ou 2 chiffres"},
    ["DAY2"] = {"d",nil,nil, "Numéro du jour du mois sur 2 chiffres"}, ["DAYNAME"] = {"l",nil,nil, "Nom du jour"},
    ["DAYABBREV"] = {"D",nil,nil, "Nom abrégé du jour"}, ["DOW"] = {"N",nil,nil, "Numéro du jour de la semaine (ISO8601)"},
    ["DOY"] = {"z",nil,nil, "Numéro du jour dans l'année sur 1 à 3 chiffres"}, ["DOY3"] = {"z",p.ft_1_2,3, "Numéro du jour dans l'année sur 3 chiffres"},
    ["TIME"] = {"H:i",nil,nil, "Heure au format HH:MM"}, ["HOUR"] = {"G",nil,nil, "Heure sur 1 ou 2 chiffres"},
    ["HOUR1"] = {"G",nil,nil, "Heure sur 1 ou 2 chiffres"}, ["HOUR2"] = {"H",nil,nil, "Heure sur 2 chiffres"},
    ["MIN"] = {"i",nil,nil, "Minute sur 2 chiffres"},  ["MIN2"] = {"i",nil,nil, "Minute sur 2 chiffres"},
    ["MIN1"] = {"i",p.ft_2_1,nil, "Minute sur 1 ou 2 chiffres"}, ["SEC"] = {"s",nil,nil, "Seconde sur 2 chiffres"},
    ["SEC2"] = {"s",nil,nil, "Seconde sur 2 chiffres"}, ["SEC1"] = {"s",p.ft_2_1,nil, "Seconde sur 1 ou 2 chiffres"},
    ["UNIX"] = {"U",nil,nil, "Temps au format UNIX"}, ["TIMESTAMP"] = {"YmdHis",nil,nil, "Temps au format AAAAMMJJHHmmSS"}
}

-- fonction "#ifexist", en attendant que mw.title soit intégré et fournisse cette fonctionnalité
function p.ifexist(page, frame)
    if (page == nil or type(page) ~= "string" or page == "") then
        return false
    end
    local res = frame:preprocess("{{#ifexist:" .. page .. "|oui}}")
    if (res == "oui") then
        return true
    else
        return false
    end
end

-- vire les espaces au début et à la fin
function p.nettoie(texte)
    if (texte == nil or texte == "") then
        return ""
    end
    if (type(texte) ~= "string") then
        return ""
    end
    return mw.ustring.gsub(mw.ustring.gsub(texte, "^%s*", ""), "%s*$", "")
end


-- retourne l'élément de date/heure demandé en suivant le format
-- des {{LOCALYEAR}}, {{LOCALTIME}} …
function p.selecteur_date(frame, larg)
    local quoi
    -- spécial : si larg ~= nil on est appelé depuis une autre fonction,
    -- on l'utilise comme paramètre
    if (larg == nil) then
        -- paramètres. frame.args pour le moment durant les tests
        local args = frame.args
        -- local args = frame:getParent().args

        -- gestion des paramètres : ce qui est demandé
        quoi = p.nettoie(args[1])
    else
        quoi = larg
    end

    -- validation
    if (quoi == "") then
        return "{{???}}"
    end
    
    -- commence par LOCAL ou par CURRENT ?
    -- "mode" contient l'option à passer à formatDate (local ou UTC),
    -- et "sel" contient le mot-clé d'accès
    local mode = true
    local sel = ""
    local tst = string.match(quoi, "^LOCAL")
    if (tst ~= nil) then
        -- heure locale
        sel = string.match(quoi, "^LOCAL(.*)$")
        -- on recupère l'heure locale
        mode = true
    else
        tst = string.match(quoi, "^CURRENT")
        if (tst ~= nil) then
            -- heure UTC
            sel = string.match(quoi, "^CURRENT(.*)$")
            -- on récupère l'heure UTC
            mode = false
        else
            -- code invalide
            return "C/L {{" .. quoi .. "}}"
        end
    end

    -- on cherche l'élément demandé dans la table
    local act = p.access[sel]
    if (act == nil) then
        return " A {{" .. quoi .. "}}"
    end

    -- on récupère un objet pour le currentLanguage
    local loc = mw.getContentLanguage()

    -- on récupère le retour de formatDate au format indiqué
    local resu = loc:formatDate(act[1], nil, mode)
    -- si il y a une fonction associée on l'appelle
    if (act[2] ~= nil) then
        resu = act[2](resu, act[3])
    end
    
    -- on retourne le résultat
    return resu
end


-- fonction d'auto-documentation. Génère en sortie un tableau contenant toutes les
-- valeurs possibles avec leur résultat
function p.selecteur_date_doc(frame)
    local res = ""

    -- on génère une table des éléments existant, afin de pouvoir faire un parcours par
    -- ordre alphabétique
    local tbl = {}
    for code, v in pairs(p.access) do
        table.insert(tbl, code) -- on range
    end
    table.sort(tbl) -- on trie

    -- entete
    res = res .. '<table class="wikitable"><caption>Liste des éléments reconnus par ce module</caption>'
    res = res .. "<tr><th>Modèle</th><th>Valeur modèle</th><th>Valeur module</th><th>Description</th></tr>"
    
    -- on fait d'abord les CURRENT
    for iii, code in ipairs(tbl) do
        -- table
        res = res .. "<tr><td><nowiki>{{CURRENT" .. code .. "}}</nowiki></td>"
        local tst = frame:preprocess("{{CURRENT" .. code .. "}}")
        if (mw.ustring.find(tst, "[[:Modèle:", 1, true) ~= nil) then
            tst = "''inexistant''"
        end
        res = res .. "<td>" .. tst .. "</td>"
        -- on récupère le résultat
        local tmp = p.selecteur_date(frame, "CURRENT" .. code)
        res = res .. "<td>" .. tmp .. "</td>"
        
        -- la doc
        res = res .. "<td>" .. (p.access[code][4] or "-") .. " (UTC)</td></tr>"
    end
    -- on fait ensuite les LOCAL
    for iii, code in ipairs(tbl) do
        -- table
        res = res .. "<tr><td><nowiki>{{LOCAL" .. code .. "}}</nowiki></td>"
        local tst = frame:preprocess("{{LOCAL" .. code .. "}}")
        if (mw.ustring.find(tst, "[[:Modèle:", 1, true) ~= nil) then
            tst = "''inexistant''"
        end
        res = res .. "<td>" .. tst .. "</td>"
        -- on récupère le résultat
        local tmp = p.selecteur_date(frame, "LOCAL" .. code)
        res = res .. "<td>" .. tmp .. "</td>"
        
        -- la doc
        res = res .. "<td>" .. (p.access[code][4] or "-") .. " (local)</td></tr>"
    end

    -- fin
    res = res .. "</table>"
    
    return frame:preprocess(res)
end


return p