Module:DatesWD: Difference between revisions
Appearance
Content deleted Content added
oh |
change |
||
Line 4: | Line 4: | ||
local err = "" |
local err = "" |
||
function |
local function purif(str) |
||
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 |
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" |
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 |
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 |
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 |
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 |
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 |
return error("Unable to recognize date") |
||
end |
end |
||
return |
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 |
local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out} |
||
return |
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