Module:LatestUpdate: Difference between revisions

From The Deadlock Wiki
Jump to navigation Jump to search
No edit summary
added days_since_date to calculate time since any given date
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
local p = {}
local p = {}


-- Load JSON content from a page
local data = mw.loadJsonData("Data:LatestUpdate.json")
local data = mw.loadJsonData("Data:LatestUpdate.json")
local update = data.latest_update or {}
local update = data.latest_update or {}


-- Month name → number mapping
local month_map = {
local month_map = {
     January = 1,
     January = 1,
Line 19: Line 17:
     November = 11,
     November = 11,
     December = 12
     December = 12
}
-- Plural rules
local plural_rules = {
    -- English
    en = function(n)
        return n == 1 and 1 or 2
    end,
    -- Spanish
    es = function(n)
        return n == 1 and 1 or 2
    end,
    -- French
    fr = function(n)
        return (n == 0 or n == 1) and 1 or 2
    end,
    -- Korean (no plural distinction)
    ko = function(n)
        return 1
    end,
    -- Russian
    ru = function(n)
        if n % 10 == 1 and n % 100 ~= 11 then
            return 1
        elseif n % 10 >= 2 and n % 10 <= 4 and (n % 100 < 10 or n % 100 >= 20) then
            return 2
        else
            return 3
        end
    end,
    -- Turkish
    tr = function(n)
        return 1
    end,
    -- Czech
    cs = function(n)
        if n == 1 then
            return 1
        elseif n >= 2 and n <= 4 then
            return 2
        else
            return 3
        end
    end,
    -- Chinese (simplified)
    ["zh-hans"] = function(n)
        return 1
    end,
    -- Chinese (traditional)
    ["zh-hant"] = function(n)
        return 1
    end,
    -- uncomment when needed
    -- pl = function(n)
    --    if n == 1 then return 1
    --    elseif n % 10 >= 2 and n % 10 <= 4 and (n % 100 < 10 or n % 100 >= 20) then return 2
    --    else return 3 end
    -- end,
    -- uk = function(n)
    --    if n % 10 == 1 and n % 100 ~= 11 then return 1
    --    elseif n % 10 >= 2 and n % 10 <= 4 and (n % 100 < 10 or n % 100 >= 20) then return 2
    --    else return 3 end
    -- end,
    -- de = function(n)
    --    return n == 1 and 1 or 2
    -- end,
    -- it = function(n)
    --    return n == 1 and 1 or 2
    -- end,
    -- pt = function(n)
    --    return n == 1 and 1 or 2
    -- end
}
local translations = {
    en = {
        [1] = "%d day ago",
        [2] = "%d days ago"
    },
    es = {
        [1] = "hace %d día",
        [2] = "hace %d días"
    },
    fr = {
        [1] = "il y a %d jour",
        [2] = "il y a %d jours"
    },
    ko = {
        [1] = "%d일 전"
    },
    ru = {
        [1] = "%d день назад",
        [2] = "%d дня назад",
        [3] = "%d дней назад"
    },
    tr = {
        [1] = "%d gün önce"
    },
    cs = {
        [1] = "před %d dnem",
        [2] = "před %d dny",
        [3] = "před %d dny"
    },
    ["zh-hans"] = {
        [1] = "%d天前"
    },
    ["zh-hant"] = {
        [1] = "%d天前"
    },
    -- uncomment when needed
    -- pl = {
    --    [1] = "%d dzień temu",
    --    [2] = "%d dni temu",
    --    [3] = "%d dni temu"
    -- },
    -- uk = {
    --    [1] = "%d день тому",
    --    [2] = "%d дні тому",
    --    [3] = "%d днів тому"
    -- },
    -- de = {
    --    [1] = "vor %d Tag",
    --    [2] = "vor %d Tagen"
    -- },
    -- it = {
    --    [1] = "%d giorno fa",
    --    [2] = "%d giorni fa"
    -- },
    -- pt = {
    --    [1] = "há %d dia",
    --    [2] = "há %d dias"
    -- }
}
-- Special-case wording for 0 and 1 days, keyed by day count.
-- A language missing an entry here falls back to the plural forms above.
local relative_days = {
    en = {
        [0] = "today",
        [1] = "yesterday"
    },
    es = {
        [0] = "hoy",
        [1] = "ayer"
    },
    fr = {
        [0] = "aujourd'hui",
        [1] = "hier"
    },
    ko = {
        [0] = "오늘",
        [1] = "어제"
    },
    ru = {
        [0] = "сегодня",
        [1] = "вчера"
    },
    tr = {
        [0] = "bugün",
        [1] = "dün"
    },
    cs = {
        [0] = "dnes",
        [1] = "včera"
    },
    ["zh-hans"] = {
        [0] = "今天",
        [1] = "昨天"
    },
    ["zh-hant"] = {
        [0] = "今天",
        [1] = "昨天"
    },
    -- uncomment when needed
    -- pl = {
    --    [0] = "dzisiaj",
    --    [1] = "wczoraj"
    -- },
    -- uk = {
    --    [0] = "сьогодні",
    --    [1] = "вчора"
    -- },
    -- de = {
    --    [0] = "heute",
    --    [1] = "gestern"
    -- },
    -- it = {
    --    [0] = "oggi",
    --    [1] = "ieri"
    -- },
    -- pt = {
    --    [0] = "hoje",
    --    [1] = "ontem"
    -- }
}
}


Line 37: Line 273:
end
end


local function getCurrentTime()
    local frame = mw.getCurrentFrame()
    local now_str = frame:callParserFunction("CURRENTTIMESTAMP", "")
    return os.time({
        year = tonumber(string.sub(now_str, 1, 4)),
        month = tonumber(string.sub(now_str, 5, 6)),
        day = tonumber(string.sub(now_str, 7, 8)),
        hour = 0
    })
end
-- Calculate days since last update
function p.days_since()
function p.days_since()
     local month_number = getMonthNumber(update.month)
     local month_number = getMonthNumber(update.month)
Line 64: Line 287:
     })
     })


     local now = getCurrentTime()
     local now = os.time()


     local diff_seconds = os.difftime(now, update_time)
     local diff_seconds = os.difftime(now, update_time)
Line 76: Line 299:
end
end


-- Return formatted text (e.g. "1 day ago", "5 days ago")
p.days_since_date = function(frame)
function p.days_since_text()
 
    local update_time = os.time({
        year = frame.args[3],
        month = frame.args[1],
        day = frame.args[2],
        hour = 0
    })
 
    local now = os.time()
 
    local diff_seconds = os.difftime(now, update_time)
    local days = math.floor(diff_seconds / 86400)
 
    if days < 0 then
        return 0
    end
 
    return days
end
 
local function normalize_lang(lang)
    if not lang or lang == "" then
        return "en"
    end
 
    return string.gsub(lang, "^/", "")
end
 
function p.days_since_text(frame)
    local args = frame.args or {}
 
    local lang = normalize_lang(args.lang or args[1] or "en")
 
    if not translations[lang] then
        lang = "en"
    end
 
     local days = p.days_since()
     local days = p.days_since()


     return days .. (days == 1 and " day ago" or " days ago")
     local relative = relative_days[lang]
    if relative and relative[days] then
        return relative[days]
    end
 
    local plural_rule = plural_rules[lang] or plural_rules.en
    local form_index = plural_rule(days)
 
    local template = translations[lang][form_index]
 
    return string.format(template, days)
end
end


return p
return p

Latest revision as of 13:46, 21 July 2026

Overview

[edit source]

This module calculates the days since the last update stored in Data:LatestUpdate.json and sends to Module:UpdateExcerpt to be displayed by Template:Deadlock Wiki/UpdateExcerpt. It can also be called to calculate the time since any given date, in days.

Examples

[edit source]

days_since_date

[edit source]

This function can be called to calculate the days passed from a given date, using the format "Month/Day/Year". "Month" has to be in numbers.

For days since January 30 2026:

{{#invoke:LatestUpdate|days_since_date|1|30|2026}}

225

days_since

[edit source]

This is an automated function that calculates the days since the latest update stored in Data:LatestUpdate.json.

days_since_text

[edit source]

This is an automated function that wraps the "days_since" data in a localized text template to be used by Module:UpdateExcerpt.


local p = {}

local data = mw.loadJsonData("Data:LatestUpdate.json")
local update = data.latest_update or {}

local month_map = {
    January = 1,
    February = 2,
    March = 3,
    April = 4,
    May = 5,
    June = 6,
    July = 7,
    August = 8,
    September = 9,
    October = 10,
    November = 11,
    December = 12
}

-- Plural rules
local plural_rules = {

    -- English 
    en = function(n)
        return n == 1 and 1 or 2
    end,

    -- Spanish
    es = function(n)
        return n == 1 and 1 or 2
    end,

    -- French
    fr = function(n)
        return (n == 0 or n == 1) and 1 or 2
    end,

    -- Korean (no plural distinction)
    ko = function(n)
        return 1
    end,

    -- Russian
    ru = function(n)
        if n % 10 == 1 and n % 100 ~= 11 then
            return 1
        elseif n % 10 >= 2 and n % 10 <= 4 and (n % 100 < 10 or n % 100 >= 20) then
            return 2
        else
            return 3
        end
    end,

    -- Turkish
    tr = function(n)
        return 1
    end,

    -- Czech
    cs = function(n)
        if n == 1 then
            return 1
        elseif n >= 2 and n <= 4 then
            return 2
        else
            return 3
        end
    end,

    -- Chinese (simplified)
    ["zh-hans"] = function(n)
        return 1
    end,

    -- Chinese (traditional)
    ["zh-hant"] = function(n)
        return 1
    end,

    -- uncomment when needed
    -- pl = function(n)
    --     if n == 1 then return 1
    --     elseif n % 10 >= 2 and n % 10 <= 4 and (n % 100 < 10 or n % 100 >= 20) then return 2
    --     else return 3 end
    -- end,

    -- uk = function(n)
    --     if n % 10 == 1 and n % 100 ~= 11 then return 1
    --     elseif n % 10 >= 2 and n % 10 <= 4 and (n % 100 < 10 or n % 100 >= 20) then return 2
    --     else return 3 end
    -- end,

    -- de = function(n)
    --     return n == 1 and 1 or 2
    -- end,

    -- it = function(n)
    --     return n == 1 and 1 or 2
    -- end,

    -- pt = function(n)
    --     return n == 1 and 1 or 2
    -- end
}

local translations = {

    en = {
        [1] = "%d day ago",
        [2] = "%d days ago"
    },

    es = {
        [1] = "hace %d día",
        [2] = "hace %d días"
    },

    fr = {
        [1] = "il y a %d jour",
        [2] = "il y a %d jours"
    },

    ko = {
        [1] = "%d일 전"
    },

    ru = {
        [1] = "%d день назад",
        [2] = "%d дня назад",
        [3] = "%d дней назад"
    },

    tr = {
        [1] = "%d gün önce"
    },

    cs = {
        [1] = "před %d dnem",
        [2] = "před %d dny",
        [3] = "před %d dny"
    },

    ["zh-hans"] = {
        [1] = "%d天前"
    },

    ["zh-hant"] = {
        [1] = "%d天前"
    },

    -- uncomment when needed

    -- pl = {
    --     [1] = "%d dzień temu",
    --     [2] = "%d dni temu",
    --     [3] = "%d dni temu"
    -- },

    -- uk = {
    --     [1] = "%d день тому",
    --     [2] = "%d дні тому",
    --     [3] = "%d днів тому"
    -- },

    -- de = {
    --     [1] = "vor %d Tag",
    --     [2] = "vor %d Tagen"
    -- },

    -- it = {
    --     [1] = "%d giorno fa",
    --     [2] = "%d giorni fa"
    -- },

    -- pt = {
    --     [1] = "há %d dia",
    --     [2] = "há %d dias"
    -- }
}

-- Special-case wording for 0 and 1 days, keyed by day count.
-- A language missing an entry here falls back to the plural forms above.
local relative_days = {

    en = {
        [0] = "today",
        [1] = "yesterday"
    },

    es = {
        [0] = "hoy",
        [1] = "ayer"
    },

    fr = {
        [0] = "aujourd'hui",
        [1] = "hier"
    },

    ko = {
        [0] = "오늘",
        [1] = "어제"
    },

    ru = {
        [0] = "сегодня",
        [1] = "вчера"
    },

    tr = {
        [0] = "bugün",
        [1] = "dün"
    },

    cs = {
        [0] = "dnes",
        [1] = "včera"
    },

    ["zh-hans"] = {
        [0] = "今天",
        [1] = "昨天"
    },

    ["zh-hant"] = {
        [0] = "今天",
        [1] = "昨天"
    },

    -- uncomment when needed

    -- pl = {
    --     [0] = "dzisiaj",
    --     [1] = "wczoraj"
    -- },

    -- uk = {
    --     [0] = "сьогодні",
    --     [1] = "вчора"
    -- },

    -- de = {
    --     [0] = "heute",
    --     [1] = "gestern"
    -- },

    -- it = {
    --     [0] = "oggi",
    --     [1] = "ieri"
    -- },

    -- pt = {
    --     [0] = "hoje",
    --     [1] = "ontem"
    -- }
}

function p.month()
    return update.month or ""
end

function p.day()
    return update.day or ""
end

function p.year()
    return update.year or ""
end

local function getMonthNumber(monthName)
    return month_map[monthName]
end

function p.days_since()
    local month_number = getMonthNumber(update.month)

    if not month_number or not update.day or not update.year then
        return 0
    end

    local update_time = os.time({
        year = tonumber(update.year),
        month = month_number,
        day = tonumber(update.day),
        hour = 0
    })

    local now = os.time()

    local diff_seconds = os.difftime(now, update_time)
    local days = math.floor(diff_seconds / 86400)

    if days < 0 then
        return 0
    end

    return days
end

 p.days_since_date = function(frame)

    local update_time = os.time({
        year = frame.args[3],
        month = frame.args[1],
        day = frame.args[2],
        hour = 0
    })

    local now = os.time()

    local diff_seconds = os.difftime(now, update_time)
    local days = math.floor(diff_seconds / 86400)

    if days < 0 then
        return 0
    end

    return days
end

local function normalize_lang(lang)
    if not lang or lang == "" then
        return "en"
    end

    return string.gsub(lang, "^/", "")
end

function p.days_since_text(frame)
    local args = frame.args or {}

    local lang = normalize_lang(args.lang or args[1] or "en")

    if not translations[lang] then
        lang = "en"
    end

    local days = p.days_since()

    local relative = relative_days[lang]
    if relative and relative[days] then
        return relative[days]
    end

    local plural_rule = plural_rules[lang] or plural_rules.en
    local form_index = plural_rule(days)

    local template = translations[lang][form_index]

    return string.format(template, days)
end

return p