Module:D'ni Time

From Guild of Archivists
Revision as of 02:02, 6 August 2020 by 67.183.237.169 (talk)
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Documentation for this module may be created at Module:D'ni Time/doc

-- THIS IS OBVIOUSLY NOT DONE! DO NOT TOUCH! -Vee

local p = {}

local args = {}
local origArgs
local root

-- Declare important constants
local refDniHahr = 9647
local msPerHahr = 31556925216
local prorahnteePerHahr = 10 * 29 * 5 * 25 * 25 * 25
local msPerProrahn = msPerHahr / prorahnteePerHahr
local refProrahnteePerHahr = 9647 * 290 * 5 * 25 * 25 * 25

local leapSecTimeStamps = {2272060800, 2287785600, 2303683200, 2335219200, 2366755200, 2398291200, 2429913600, 2461449600, 2492985600, 2524521600, 2571782400, 2603318400, 2634854400, 2698012800, 2776982400, 2840140800, 2871676800, 2918937600, 2950473600, 2982009600, 3029443200, 3076704000, 3124137600, 3345062400, 3439756800, 3550089600, 3644697600, 3692217600}
local LeapSecOffset = 10

local function ConvertLeapSecTimeStamps()
-- convert LeapSecTimeStamps from NTP epoch (number of seconds since 1900-01-01 00:00:00)
-- to Unix standard (number of milliseconds since 1970-01-01 00:00:00)

   delta = os.time({year=1900, month=1, day=1, hour=0, min=0})
   for key,value in pairs(leapSecTimeStamps) do
      leapSecTimeStamps[key] = value + delta
   end
end

local function AdjustForLeapSeconds(timestamp)
-- Adjust timestamp for leap seconds
   leapsecs = 0
   for key,value in pairs(leapSecTimeStamps) do
      if timestamp >= value then
         leapsecs = leapsecs + 1
      end
   end
   if leapsecs > 0 then
      leapsecs = leapsecs + (LeapSecOffset - 1)
   end 
   return timestamp + leapsecs
end

local function DejustForLeapSeconds(timestamp)
-- Adjust timestamp for leap seconds the other way
   leapsecs = 0
   for key,value in pairs(leapSecTimeStamps) do
      if timestamp >= value then
         leapsecs = leapsecs + 1
      end
   end
   if leapsecs > 0 then
      leapsecs = leapsecs + (LeapSecOffset - 1)
   end 
   return timestamp - leapsecs
end

local function makeSurfaceTimeStamp(timeStampTable)
-- convert a UTC date-time to a adjusted timestamp
   temp = os.time(timeStampTable)
   return AdjustForLeapSeconds(temp)
end

-- Run conversion of leapseconds and conversion of reference Timestamp here,
-- since these require the above functions to be already declared

ConvertLeapSecTimeStamps()
local refTimeStamp = makeSurfaceTimeStamp({year=1991, month=4, day=21, hour=16, min=54})

local function adjust(dniTime)
-- Ensure DniTime values are within bounds
        while (dniTime['prorahn'] > 25) do
            dniTime['prorahn'] = dniTime['prorahn'] - 25
            dniTime['gorahn'] = dniTime['gorahn'] + 1
        end

        while (dniTime['prorahn'] < 0) do
            dniTime['prorahn'] = dniTime['prorahn'] + 25
            dniTime['gorahn'] = dniTime['gorahn'] - 1
        end

        while (dniTime['gorahn'] > 25) do
            dniTime['gorahn'] = dniTime['gorahn'] - 25;
            dniTime['tahvo'] = dniTime['tahvo'] + 1;
        end

        while (dniTime['gorahn'] < 0) do
            dniTime['gorahn'] = dniTime['gorahn'] + 25
            dniTime['tahvo'] = dniTime['tahvo'] - 1
        end

        while (dniTime['tahvo'] > 25) do
            dniTime['tahvo'] = dniTime['tahvo'] - 25
            dniTime['gartahvo'] = dniTime['gartahvo'] + 1
        end

        while (dniTime['tahvo'] < 0) do
            dniTime['tahvo'] = dniTime['tahvo'] + 25
            dniTime['gartahvo'] = dniTime['gartahvo'] - 1
        end

        while (dniTime['gartahvo'] > 5) do
            dniTime['gartahvo'] = dniTime['gartahvo'] - 5
            dniTime['yahr'] = dniTime['yahr'] + 1
        end

        while (dniTime['gartahvo'] < 0) do
            dniTime['gartahvo'] = dniTime['gartahvo'] + 5
            dniTime['yahr'] = dniTime['yahr'] - 1
        end

        while (dniTime['yahr'] > 29) do
            dniTime['yahr'] = dniTime['yahr'] - 29
            dniTime['vailee'] = dniTime['vailee'] + 1
        end

        while (dniTime['yahr'] < 0) do
            dniTime['yahr'] = dniTime['yahr'] + 29
            dniTime['vailee'] = dniTime['vailee'] - 1
        end

        while (dniTime['vailee'] > 9) do
            dniTime['vailee'] = dniTime['vailee'] - 10
            dniTime['hahr'] = dniTime['hahr'] + 1;
        end

        while (dniTime['vailee'] < 0) do
            dniTime['vailee'] = dniTime['vailee'] + 10
            dniTime['hahr'] = dniTime['hahr'] - 1
        end

        return dniTime
end


local function surface2DniTime(surfaceTimeStamp)
-- Given a surfaceTimestamp
-- Return a DniTime (table)

   dniTime = {}

   delta = (surfaceTimeStamp - refTimeStamp) * 1000

   dniTime['hahr'] = math.floor(delta / msPerHahr)

   delta = delta - (dniTime['hahr'] * msPerHahr)

   delta = delta * (prorahnteePerHahr / msPerHahr)

   dniTime['vailee'] = math.floor(delta / (29 * 5 * 25 * 25 * 25))
   delta = delta - (dniTime['vailee'] * (29 * 5 * 25 * 25 * 25))

   dniTime['yahr'] = math.floor(delta / (5 * 25 * 25 * 25))
   delta = delta - (dniTime['yahr'] * (5 * 25 * 25 * 25))

   dniTime['gartahvo'] = math.floor(delta / (25 * 25 * 25))
   delta = delta - (dniTime['gartahvo'] * (25 * 25 * 25))

   dniTime['tahvo'] = math.floor(delta / (25 * 25))
   delta = delta - (dniTime['tahvo'] * (25 * 25))

   dniTime['gorahn'] = math.floor(delta / 25)
   delta = delta - (dniTime['gorahn'] * 25)

   dniTime['prorahn'] = math.floor(delta)

   dniTime['hahr'] = dniTime['hahr'] + refDniHahr
   dniTime['yahr'] = dniTime['yahr'] + 1

   return adjust(dniTime)
end

local function dni2SurfaceTime(dniTime)
-- Given a DniTime (table)
-- Return a surfacteTimestamp
   dniTime = adjust(dniTime)

   dTimeInProrahntee = dniTime['prorahn'] + (dniTime['gorahn'] * 25) + (dniTime['tahvo'] * 25 * 25) + (dniTime['gartahvo'] * 25 * 25 * 25) + ((dniTime['yahr'] - 1) * 5 * 25 * 25 * 25) + ((dniTime['vailee']) * 29 * 5 * 25 * 25 * 25) + (dniTime['hahr'] * 290 * 5 * 25 * 25 * 25)

   dTimeDelta = refProrahnteePerHahr - dTimeInProrahntee 
   
   dTimeDelta = dTimeDelta * msPerProrahn

   dTimeDelta = (refTimeStamp * 1000) - dTimeDelta

   surfaceTimestamp = DejustForLeapSeconds(dTimeDelta/1000)

   return os.date("*t",surfaceTimestamp)
end

-- ==Display Functions==

local function getVaileeName(vailee, useDniFont)
-- Return name of vailee given number (zero-indexed)
-- If useDniFont is true, return it in Dnifont text 

    useDniFont = useDniFont or false

    vaileetee = {"Leefo","Leebro","Leesahn","Leetar","Leevot","Leevofo","Leevobro","Leevosahn","Leevotar","Leenovoo"}
    vaileetee_dnifont = {"lEfo","lEbro","lEsan","lEtar","lEvot","lEvofo","lEvobro","lEvosan","lEvotar","lEnovU"}

    if(useDniFont) then
       return vaileetee_dnifont[vailee+1]
    else
       return vaileetee[vailee+1]
    end
end

local function displayDniTime(dniTime)
-- Return dniTime (table) as string of table

   return '{'..'hahr = '..dniTime['hahr']..', vailee = '..dniTime['vailee']..', vaileeName = '..getVaileeName(dniTime['vailee'])..', yahr = '..dniTime['yahr']..', gartahvo = '..dniTime['gartahvo']..', tahvo = '..dniTime['tahvo']..', gorahn = '..dniTime['gorahn']..', prorahn = '..dniTime['prorahn']..'}'

end

local function displaySurfaceTime(surface)
-- Return surfaceTime (table) as string of table

   return '{'..'year = '..surface['year']..', month = '..surface['month']..', day = '..surface['day']..', hour = '..surface['hour']..', min = '..surface['min']..', sec = '..surface['sec']..'}'
end

local function formatSurfaceTime(surfaceTime)

   os.date("%c",os.time(surfaceTime))

end

-- =============================================================================

local function preprocessSingleArg(argName)
    -- If the argument exists and isn't blank, add it to the argument table.
    -- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
    if origArgs[argName] and origArgs[argName] ~= '' then
        args[argName] = origArgs[argName]
    end
end

local function preprocessArgs(prefixTable, step)
    -- Assign the parameters with the given prefixes to the args table, in order, in batches
    -- of the step size specified. This is to prevent references etc. from appearing in the
    -- wrong order. The prefixTable should be an array containing tables, each of which has
    -- two possible fields, a "prefix" string and a "depend" table. The function always parses
    -- parameters containing the "prefix" string, but only parses parameters in the "depend"
    -- table if the prefix parameter is present and non-blank.
    if type(prefixTable) ~= 'table' then
        error("Non-table value detected for the prefix table", 2)
    end
    if type(step) ~= 'number' then
        error("Invalid step value detected", 2)
    end
    
    -- Get arguments without a number suffix, and check for bad input.
    for i,v in ipairs(prefixTable) do
        if type(v) ~= 'table' or type(v.prefix) ~= "string" or (v.depend and type(v.depend) ~= 'table') then
            error('Invalid input detected to preprocessArgs prefix table', 2)
        end
        preprocessSingleArg(v.prefix)
        -- Only parse the depend parameter if the prefix parameter is present and not blank.
        if args[v.prefix] and v.depend then
            for j, dependValue in ipairs(v.depend) do
                if type(dependValue) ~= 'string' then
                    error('Invalid "depend" parameter value detected in preprocessArgs')
                end
                preprocessSingleArg(dependValue)
            end
        end
    end

    -- Get arguments with number suffixes.
    local a = 1 -- Counter variable.
    local moreArgumentsExist = true
    while moreArgumentsExist == true do
        moreArgumentsExist = false
        for i = a, a + step - 1 do
            for j,v in ipairs(prefixTable) do
                local prefixArgName = v.prefix .. tostring(i)
                if origArgs[prefixArgName] then
                    moreArgumentsExist = true -- Do another loop if any arguments are found, even blank ones.
                    preprocessSingleArg(prefixArgName)
                end
                -- Process the depend table if the prefix argument is present and not blank, or
                -- we are processing "prefix1" and "prefix" is present and not blank, and
                -- if the depend table is present.
                if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then
                    for j,dependValue in ipairs(v.depend) do
                        local dependArgName = dependValue .. tostring(i)
                        preprocessSingleArg(dependArgName)
                    end
                end
            end
        end
        a = a + step
    end
end

function p.test(frame)
    -- If called via #invoke, use the args passed into the invoking template.
    -- Otherwise, for testing purposes, assume args are being passed directly in.
    if frame == mw.getCurrentFrame() then
        origArgs = frame:getParent().args
    else
        origArgs = frame
    end
    
    -- Parse the data parameters
    

    output = os.time({year=1900, month=1, day=1, hour=0, min=0}) .. "<br/>" .. refTimeStamp .."<br/>" .. displaySurfaceTime(os.date("*t",refTimeStamp))
    output = output .. "<br/>" .. displaySurfaceTime(os.date("*t",63100800)) .. "<br/>"
    output = output .. displayDniTime(surface2DniTime(makeSurfaceTimeStamp({year=2020, month=7, day=29, hour=16, min=0}))).."<br/>---"
    output = output .. formatSurfaceTime(displaySurfaceTime(dni2SurfaceTime({hahr = 9676, vailee = 2, yahr = 22, gartahvo = 1, tahvo = 18, gorahn = 21, prorahn = 24}))).."<br/>---"



    return output
end

return p