Jump to content

Module:DatesWD

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Carn (talk | contribs) at 13:35, 10 January 2020 (oh). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

local p = {}
local bool_to_number={ [true]=1, [false]=0 }
local getArgs = require('Module:Arguments').getArgs
local err = ""

function p.NthDay( frame )
    local args = getArgs(frame, { frameOnly = true })
    local num = math.floor(tonumber(args[1])) 
    local wday = math.floor(tonumber(args[2])) 
    local mont = math.floor(tonumber(args[3])) 
    local yea = math.floor(tonumber(args[4])) 
    local format = args[5]
    local bool_to_number={ [true]=1, [false]=0 } 
    local err = "---"
    if num < -5 or num > 5 then 
        error("The number must be between -5 and 5")
    elseif num == 0 then
        error("The number must not be zero")
    end
    if wday < 0 or wday > 6 then 
        error("The day of the week must be between 0 and 6") end
    if mont < 0 or mont > 12 then 
        error("The month must be between 1 and 12") end
    if yea < 0 or yea > 9999 then 
        error("Wrong year number") end
    if num > 0 and num < 6 then
        local m_start = os.time{year=yea, month=mont, day=1, hour=0}
        local m_wds = tonumber(os.date("%w", m_start)) 
        local start_shift = (
            (num - bool_to_number[wday >= m_wds]) * 7 
            - (m_wds - wday)
            ) * 24 * 60 * 60
        local tim = m_start + start_shift
        if tonumber(os.date("%m", tim)) == mont then
            return (os.date(format, tim))
        else
            return (err)
        end
    elseif num < 0 and num > -6 then
        local m_end = os.time{year = yea, month = mont + 1, day = 1, hour = 0} - 24 * 60 * 60
        local m_wde = tonumber(os.date("%w", m_end))
        local end_shift = ((math.abs(num + 1) + bool_to_number[wday > m_wde]) * 7 
            + (m_wde - wday)) * 24 * 60 * 60
        local tim = m_end - end_shift
        if tonumber(os.date("%m", tim)) == mont then
            return (os.date(format, tim))
        else
            return (err)
        end
    end
end

local purif = function (str)
    if str == "" or str == nil then 
        return nil 
    elseif type(tonumber(str)) == "number" then
        return math.floor(tonumber(str))
    else
        return nil
    end
    -- need .5 -- ,5 number format converter
    error("You shouldn't read this")
end

local inbord = function (val, down, up)
	if type(up) ~= "number" or type(down) ~= "number" or type(val) ~= "number" or up < down or val < down or val > up then
		return false
    else
        return true
    end
end	

local inborders = function (val, down, up)
	if up < down or type(up) ~= "number" or type(down) ~= "number" then
		err = "Range " .. down .. "-" .. up .. " is not valid."
		return error(err)
    elseif type(val) ~= "number" then
	    err = "Value " .. val .. " is not valid"
	    return error(err)
    elseif val < down or val > up then 
    	err = "Value " .. val .. " not in the " .. down .. "-" .. up .. " range."
        return error(err)
    else
        return val
    end
end	

function isdateret ( chain )
	if type(chain) ~= "table" then
		err = "Wrong type: " .. type(chain)
		return error(err)
	elseif (not chain.year) or (not chain.month) or (not chain.day) then
		if #chain == 3 then error("Unnamed table arguments")
		else error("Wrong format") end
	elseif not inbord(chain.year,-9999,9999) then
		err = chain.year .. " is wrong year"
		error(err)
	elseif not inbord(chain.month,1,12) then
		err = chain.year .. " is wrong month"
		error(err)
	elseif not inbord(chain.day,1,31) then
		err = chain.year .. " is wrong day"
		error(err)
	else return chain end
--  more detailed check for 31.02.0000 needed
end

function isdate ( chain )
	if type(chain) == "table" and inbord(chain.year,-9999,9999) and inbord(chain.month,1,12) and inbord(chain.day,1,31) then
		return true
	else return false end
--  more detailed check for 31.02.0000 needed
--  check for other calendars needed
end

local numstr2date = function (datein)
	local nums = {}
    local dateout = {}
    for num in string.gmatch(datein,"(%d+)") do
        table.insert(nums,purif(num))
    end
    if #nums ~= 3 then error("Wrong format: 3 numbers expected")
    elseif not inbord(nums[2],1,12) then error("Wrong month")
    elseif not inbord(nums[3],1,31) then
        dateout.year = nums[3]
        dateout.month = nums[2]
        dateout.day = nums[1]
    elseif not inbord(nums[1],1,31) then
        dateout.year = nums[1]
        dateout.month = nums[2]
        dateout.day = nums[3]
    else
--		local lang = mw.getContentLanguage()
--		lang:formatDate(format,datein,true)
        return error("Unable to recognize date format")
    end
    return isdateret(dateout)
end

function gri2jd( datein )
    local year = datein.year
    local month = datein.month
    local day = datein.day
    -- проверка параметров
    if not (type(year) == 'number') then 
        return error("Wrong year")
    end
    if not (1 <= month and month <= 12) then 
        return error("Wrong month")
    end
    if not (1 <= day and day <= 31) then 
        return error("Wrong day")
    end
    -- расчёт юлианской даты
    local a = math.floor((14 - month)/12) 
    local y = year + 4800 - a
    local m = month + 12*a - 3
    local offset = math.floor(y/4) - math.floor(y/100) + math.floor(y/400) - 32045 
    local jd = day + math.floor((153*m + 2)/5) + 365*y + offset
    -- проверка попадания юлианской даты в границы между -9999 и 9999 годами Ю.К.
    local low, high = -1931076.5, 5373557.49999
    if not (low <= jd and jd <= high) then
        return error("Wrong date")
    end
    -- расчёт даты по юлианскому календарю
    local c = jd + 32082
    local d = math.floor((4*c + 3)/1461)
    local e = c - math.floor(1461*d/4)
    local m = math.floor((5*e + 2)/153)
    local year_out = d - 4800 + math.floor(m/10)
    local month_out = m + 3 - 12*math.floor(m/10)
    local day_out = e - math.floor((153*m + 2)/5) + 1
    -- вывод даты в формате ГГГГ-ММ-ДД
    local date = os.date("%Y-%m-%d", os.time{year=year_out, month=month_out, day=day_out})
    return date
end
-- =p.test(mw.getCurrentFrame():newChild{title="обычно не важно",args={"1.1.2020"}}) 

function p.test(frame)
	local args = getArgs(frame, { frameOnly = true })
	local input = args[1]
	if not input then
		return ""
	else
		local datetest = numstr2date(input)
		if isdate(datetest) then
			strout = datetest.day .. "." .. datetest.month .. "." .. datetest.year .. " = " .. gri2jd(datetest)
			return strout
		else error("Not a date")
		end
	end
	error("You shouldn't read this too")
end

return p