Jump to content

Module:DatesWD: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
oh
change
Line 4: Line 4:
local err = ""
local err = ""


function p.NthDay( frame )
local function purif(str)
local args = getArgs(frame, { frameOnly = true })
if str == "" or str == nil then
return nil
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
elseif type(tonumber(str)) == "number" then
return math.floor(tonumber(str))
return math.floor(tonumber(str))
Line 59: Line 12:
return nil
return nil
end
end
-- need .5 -- ,5 number format converter
-- need .5 -- ,5 number format converter?
error("You shouldn't read this")
end
end


local inbord = function (val, down, up)
local function inbord(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
if type(up) ~= "number" or type(down) ~= "number" or type(val) ~= "number" or up < down or val < down or val > up then
return false
return false
Line 69: Line 21:
return true
return true
end
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
end


function isdate ( chain )
local 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
if (not type(chain) == "table")
or (not inbord(chain.year,-9999,9999))
or (not inbord(chain.month,1,12))
or (not inbord(chain.day,1,31))
return true
then return false
else return false end
else return true end
-- more detailed check for 31.02.0000 needed
-- more detailed check for 31.02.0000 needed
-- check for other calendars needed
-- check for other calendars needed
end
end


local numstr2date = function (datein)
local function numstr2date(datein)
local nums = {}
local nums = {}
local dateout = {}
local dateout = {}
Line 123: Line 43:
elseif not inbord(nums[2],1,12) then error("Wrong month")
elseif not inbord(nums[2],1,12) then error("Wrong month")
elseif not inbord(nums[3],1,31) then
elseif not inbord(nums[3],1,31) then
dateout.year = nums[3]
dateout = {["year"]=nums[3], ["month"]=nums[2], ["day"]=nums[1]}
dateout.month = nums[2]
dateout.day = nums[1]
elseif not inbord(nums[1],1,31) then
elseif not inbord(nums[1],1,31) then
dateout.year = nums[1]
dateout = {["year"]=nums[1], ["month"]=nums[2], ["day"]=nums[3]}
dateout.month = nums[2]
dateout.day = nums[3]
else
else
-- local lang = mw.getContentLanguage()
-- local lang = mw.getContentLanguage()
-- lang:formatDate(format,datein,true)
-- implement lang:formatDate(format,datein,true) here
return error("Unable to recognize date format")
return error("Unable to recognize date")
end
end
return isdateret(dateout)
return dateout
end

local function date2str(datein)
if not isdate(datein) then return error("Wrong date") end
local dateout = os.date("%Y-%m-%d", os.time(datein))
return dateout
end
end


function gri2jd( datein )
function gri2jd( datein )
if not isdate(datein) then return error("Wrong date") end
local year = datein.year
local year = datein.year
local month = datein.month
local month = datein.month
local day = datein.day
local day = datein.day
-- jd calculation
-- проверка параметров
local a = math.floor((14 - month)/12)
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 y = year + 4800 - a
local m = month + 12*a - 3
local m = month + 12*a - 3
local offset = math.floor(y/4) - math.floor(y/100) + math.floor(y/400) - 32045
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
local jd = day + math.floor((153*m + 2)/5) + 365*y + offset
-- jd validation
-- проверка попадания юлианской даты в границы между -9999 и 9999 годами Ю.К.
local low, high = -1931076.5, 5373557.49999
local low, high = -1931076.5, 5373557.49999
if not (low <= jd and jd <= high) then
if not (low <= jd and jd <= high) then
return error("Wrong date")
return error("Wrong date")
end
end
return jd
-- расчёт даты по юлианскому календарю
end

function jd2jul( jd )
if type(jd) ~= "number" then return error("Wrong jd") end
-- calendar date calculation
local c = jd + 32082
local c = jd + 32082
local d = math.floor((4*c + 3)/1461)
local d = math.floor((4*c + 3)/1461)
Line 171: Line 89:
local month_out = m + 3 - 12*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 day_out = e - math.floor((153*m + 2)/5) + 1
-- output
-- вывод даты в формате ГГГГ-ММ-ДД
local date = os.date("%Y-%m-%d", os.time{year=year_out, month=month_out, day=day_out})
local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out}
return date
return dateout
end
end

-- =p.test(mw.getCurrentFrame():newChild{title="обычно не важно",args={"1.1.2020"}})
function jul2jd( datein )
if not isdate(datein) then return error("Wrong date") end
local year = datein.year
local month = datein.month
local day = datein.day
-- jd calculation
local a = math.floor((14 - month)/12)
local y = year + 4800 - a
local m = month + 12*a - 3
local offset = math.floor(y/4) - 32083
local jd = day + math.floor((153*m + 2)/5) + 365*y + offset
-- jd validation
local low, high = -1930999.5, 5373484.49999
if not (low <= jd and jd <= high) then
return error("Wrong date")
end
return jd
end

function jd2gri( jd )
-- calendar date calculation
local a = jd + 32044
local b = math.floor((4*a + 3) / 146097)
local c = a - math.floor(146097*b/4)
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 day_out = e - math.floor((153*m+2)/5)+1
local month_out = m + 3 - 12*math.floor(m/10)
local year_out = 100*b + d - 4800 + math.floor(m/10)
-- output
local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out}
return dateout
end

-- =p.NthDay(mw.getCurrentFrame():newChild{title="1",args={"1","1","1","2020","%Y-%m-%d"}})

function p.NthDay( frame )
local args = getArgs(frame, { frameOnly = true })
local num, wday, mont, yea, format =
purif(args[1]), purif(args[2]), purif(args[3]), purif(args[4]), args[5]
if not inbord(num,-5,5) then
return error("The number must be between -5 and 5")
elseif num == 0 then
return error("The number must not be zero") end
if not inbord(wday,0,6) then
return error("The day of the week must be between 0 and 6") end
if not inbord(mont,1,12) then
return error("The month must be between 1 and 12") end
if not inbord(yea,0,9999) then
return error("Wrong year number") end
if inbord(num,1,5) 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 inbord(num,-5,-1) 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

-- =p.test(mw.getCurrentFrame():newChild{title="1",args={"1.1.2020"}})


function p.test(frame)
function p.test(frame)

Revision as of 14:38, 10 January 2020

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

local function purif(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?
end

local function inbord(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 function isdate ( chain )
	if (not type(chain) == "table")
	or (not inbord(chain.year,-9999,9999))
	or (not inbord(chain.month,1,12))
	or (not inbord(chain.day,1,31))
	then return false
	else return true end
--  more detailed check for 31.02.0000 needed
--  check for other calendars needed
end

local function numstr2date(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], ["month"]=nums[2], ["day"]=nums[1]}
    elseif not inbord(nums[1],1,31) then
        dateout = {["year"]=nums[1], ["month"]=nums[2], ["day"]=nums[3]}
    else
--		local lang = mw.getContentLanguage()
--		implement lang:formatDate(format,datein,true) here
        return error("Unable to recognize date")
    end
    return dateout
end

local function date2str(datein)
	if not isdate(datein) then return error("Wrong date") end
	local dateout = os.date("%Y-%m-%d", os.time(datein))
    return dateout
end

function gri2jd( datein )
	if not isdate(datein) then return error("Wrong date") end
    local year = datein.year
    local month = datein.month
    local day = datein.day
    -- jd calculation
    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
    -- jd validation
    local low, high = -1931076.5, 5373557.49999
    if not (low <= jd and jd <= high) then
        return error("Wrong date")
    end
	return jd
end

function jd2jul( jd )
	if type(jd) ~= "number" then return error("Wrong jd") end
    -- calendar date calculation
    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
    -- output
    local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out}
    return dateout
end

function jul2jd( datein )
	if not isdate(datein) then return error("Wrong date") end
    local year = datein.year
    local month = datein.month
    local day = datein.day
    -- jd calculation
    local a = math.floor((14 - month)/12)
    local y = year + 4800 - a
    local m = month + 12*a - 3
    local offset = math.floor(y/4) - 32083
    local jd = day + math.floor((153*m + 2)/5) + 365*y + offset
    -- jd validation
    local low, high = -1930999.5, 5373484.49999
    if not (low <= jd and jd <= high) then
        return error("Wrong date")
    end
	return jd
end

function jd2gri( jd )
    -- calendar date calculation
    local a = jd + 32044
    local b = math.floor((4*a + 3) / 146097)
    local c = a - math.floor(146097*b/4)
    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 day_out =  e - math.floor((153*m+2)/5)+1
    local month_out = m + 3 - 12*math.floor(m/10)
    local year_out = 100*b + d - 4800 + math.floor(m/10)
    -- output
    local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out}
    return dateout
end

-- =p.NthDay(mw.getCurrentFrame():newChild{title="1",args={"1","1","1","2020","%Y-%m-%d"}}) 

function p.NthDay( frame )
    local args = getArgs(frame, { frameOnly = true })
    local num, wday, mont, yea, format = 
    	purif(args[1]), purif(args[2]), purif(args[3]), purif(args[4]), args[5]
    if not inbord(num,-5,5) then 
    	return error("The number must be between -5 and 5")
    elseif num == 0 then 
    	return error("The number must not be zero") end
    if not inbord(wday,0,6) then 
    	return error("The day of the week must be between 0 and 6") end
    if not inbord(mont,1,12) then 
    	return error("The month must be between 1 and 12") end
    if not inbord(yea,0,9999) then 
    	return error("Wrong year number") end
    if inbord(num,1,5) 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 inbord(num,-5,-1) 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

-- =p.test(mw.getCurrentFrame():newChild{title="1",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