Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:HebrewDate

From Wikipedia, the free encyclopedia
local p = {}

-- ==========================================================
-- 1. CORE CALENDAR MATH
-- ==========================================================
local hebrew_epoch = -1373427

local function div(a, b) return math.floor(a / b) end
local function mod(a, b) return a - math.floor(a / b) * b end

local function elapsed_days(year)
    local months = div(235 * year - 234, 19)
    local parts = 12084 + 13753 * months
    local day = 29 * months + div(parts, 25920)
    -- Dehuiyot: adjust if molad falls on Sunday, Wednesday, or Friday
    if mod(3 * (day + 1), 7) < 3 then
        return day + 1
    end
    return day
end

local function new_year_delay(year)
    local n0 = elapsed_days(year - 1)
    local n1 = elapsed_days(year)
    local n2 = elapsed_days(year + 1)
    if (n2 - n1) == 356 then return 2 end
    if (n1 - n0) == 382 then return 1 end
    return 0
end

local function hebrew_new_year(year)
    return hebrew_epoch + elapsed_days(year) + new_year_delay(year)
end

local function is_greg_leap(y)
    return (mod(y, 4) == 0 and mod(y, 100) ~= 0) or (mod(y, 400) == 0)
end

local function gregorian_to_fixed(y, m, d)
    local days = 365 * (y - 1) + div(y - 1, 4) - div(y - 1, 100) + div(y - 1, 400)
    local month_days = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}
    days = days + month_days[m]
    if m > 2 and is_greg_leap(y) then days = days + 1 end
    return days + d
end

local function get_month_length(month, is_leap, year_len)
    if month == 13 then return is_leap and 29 or 0 end
    if month == 12 then return is_leap and 30 or 29 end
    if month == 2 or month == 4 or month == 6 or month == 10 then return 29 end
    if month == 8 then return (year_len == 355 or year_len == 385) and 30 or 29 end
    if month == 9 then return (year_len == 353 or year_len == 383) and 29 or 30 end
    return 30
end

-- ==========================================================
-- 2. MAIN EXECUTION
-- ==========================================================
function p.main(frame)
    -- Get current UTC time
    local current_time = os.time()
    local t = os.date("!*t", current_time)
    
    -- If it is 6:00 PM (18:00) UTC or later, roll forward to the next day
    if t.hour >= 18 then
        current_time = current_time + 86400
        t = os.date("!*t", current_time)
    end
    
    -- Convert Gregorian date to Rata Die (Fixed days since 1 CE)
    local rd = gregorian_to_fixed(t.year, t.month, t.day)
    
    -- Find the corresponding Hebrew Year
    local appx = 1 + div((rd - hebrew_epoch) * 98496, 35975351)
    local Y = appx - 1
    while hebrew_new_year(Y + 1) <= rd do
        Y = Y + 1
    end
    
    -- Determine year characteristics
    local is_leap = mod(1 + 7 * Y, 19) < 7
    local year_len = hebrew_new_year(Y + 1) - hebrew_new_year(Y)
    
    -- Iterate through the months to find the current month and day
    local seq = {7, 8, 9, 10, 11, 12, 13, 1, 2, 3, 4, 5, 6}
    local days_remaining = rd - hebrew_new_year(Y)
    local H_month = 7
    
    for _, m in ipairs(seq) do
        local m_len = get_month_length(m, is_leap, year_len)
        if m_len > 0 then
            if days_remaining < m_len then
                H_month = m
                break
            else
                days_remaining = days_remaining - m_len
            end
        end
    end
    
    local H_day = days_remaining + 1
    
    -- Map month number to text
    local month_names = {
        [1] = "Nisan", [2] = "Iyyar", [3] = "Sivan", [4] = "Tammuz",
        [5] = "Av", [6] = "Elul", [7] = "Tishri", [8] = "Marheshvan",
        [9] = "Kislev", [10] = "Tevet", [11] = "Shevat", [12] = "Adar", [13] = "Adar II"
    }
    
    local date_no_year = H_day .. " " .. month_names[H_month]
    local date_with_year = date_no_year .. " " .. Y
    
    return "[[" .. date_no_year .. "|" .. date_with_year .. "]]"
end

return p