Module:D'ni Time

From Guild of Archivists
Revision as of 00:56, 17 August 2020 by BladeLakem (talk | contribs)
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

dnitools = require("Module:D'ni Tools")
dnifunc = require("Module:D'ni Time/dni")
surfacefunc = require("Module:D'ni Time/surface")

Date = require('Module:Date')._Date

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 vaileetee = {"Leefo","Leebro","Leesahn","Leetar","Leevot","Leevofo","Leevobro","Leevosahn","Leevotar","Leenovoo"}
local vaileetee_dnifont = {"lEfo","lEbro","lEsan","lEtar","lEvot","lEvofo","lEvobro","lEvosan","lEvotar","lEnovU"}

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['gahrtahvo'] = dniTime['gahrtahvo'] + 1
        end

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

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

        while (dniTime['gahrtahvo'] < 0) do
            dniTime['gahrtahvo'] = dniTime['gahrtahvo'] + 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)
   surface = surface or refTimeStamp

   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['gahrtahvo'] = math.floor(delta / (25 * 25 * 25))
   delta = delta - (dniTime['gahrtahvo'] * (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)
   return dniTime
end

local function dni2SurfaceTime(dniTime)
-- Given a DniTime (table)
-- Return a surfacteTimestamp
   dniTime = dniTime or {hahr = refDniHahr, vailee = 0, yahr = 1, gahrtahvo = 0, tahvo = 0, gorahn = 0, prorahn = 0}

   dniTime = adjust(dniTime)

   dTimeInProrahntee = dniTime['prorahn'] + (dniTime['gorahn'] * 25) + (dniTime['tahvo'] * 25 * 25) + (dniTime['gahrtahvo'] * 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 formatSurfaceTime(surfaceTime,format)

   format = format or 'c'
 
   lang = mw.getContentLanguage()

--   return lang:formatDate(format,"@"..makeSurfaceTimeStamp(surfaceTime))
     return lang:formatDate(format,tostring(surfaceTime['year'])..'-'..tostring(surfaceTime['month'])..'-'..tostring(surfaceTime['day'])..' '..tostring(surfaceTime['hour'])..':'..tostring(surfaceTime['min'])..':'..tostring(surfaceTime['sec']))
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

function p.surface2dni(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

    output = ""
    
    preprocessSingleArg('datetime')
    preprocessSingleArg('format')
    
    if args['datetime'] then
       surfaceTime = surfacefunc.parseSurfaceDateStr(args['datetime'])
       output = dnifunc.formatDniTime(surface2DniTime(makeSurfaceTimeStamp(surfaceTime)),args['format'])
    else 
       preprocessSingleArg('year')
       preprocessSingleArg('month')  
       preprocessSingleArg('day') 
       preprocessSingleArg('hour') 
       preprocessSingleArg('minute') 
       preprocessSingleArg('second') 

       -- Parse the data parameters
       surface = {year = args['year'], month = args['month'], day = args['day'], hour = args['hour'], min = args['minute'], sec = args['second']}

---      output =  dnifunc.displayDniTime(surface2DniTime(makeSurfaceTimeStamp(surface)),args['format'])
      output = dnifunc.formatDniTime(surface2DniTime(makeSurfaceTimeStamp(surface)),args['format'])
     end
     return output
end

function p.dni2surface(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

    preprocessSingleArg('datetime')
    preprocessSingleArg('format')
    preprocessSingleArg('input')

    if args['datetime'] then
       output = formatSurfaceTime(dni2SurfaceTime(dnifunc.parseDniDateStr(args['datetime'],args['input'])),args['format'])
    else 
      preprocessSingleArg('hahr')
      preprocessSingleArg('vailee')  
      preprocessSingleArg('yahr') 
      preprocessSingleArg('gahrtahvo') 
      preprocessSingleArg('tahvo') 
      preprocessSingleArg('gorahn')
      preprocessSingleArg('prorahn') 

      -- Parse the data parameters
      dni = {hahr = tonumber(args['hahr']), vailee = tonumber(args['vailee']), yahr = tonumber(args['yahr']), gahrtahvo = tonumber(args['gahrtahvo']), tahvo = tonumber(args['tahvo']), gorahn = tonumber(args['gorahn']), prorahn = tonumber(args['prorahn'])}

--      output = surfacefunc.displaySurfaceTime(dni2SurfaceTime(dni),args['format'])
      output = formatSurfaceTime(dni2SurfaceTime(dni),args['format'])
    end
    
    return output

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
    
    lang = mw.getContentLanguage()

    surface = {year = -7658, month = 5, day = 31, hour = 6, min = 56, sec = 58, isdst = true}
    dni = {hahr = -1, vailee = 1, yahr = 1, gahrtahvo = 1, tahvo = 1, gorahn = 1, prorahn = 1}

    output = ""
    output = output .. "<br/>"..surfacefunc.displaySurfaceTime(surface)
--    output = output .. "<br/>"..dnifunc.displayDniTime(surface2DniTime(makeSurfaceTimeStamp(surface)))
--    output = output .. "<br/>"..dnifunc.formatDniTime(surface2DniTime(makeSurfaceTimeStamp(surface)))
    output = output .. "<br/>"..dnifunc.displayDniTime(dni)
    output = output .. "<br/>"..surfacefunc.displaySurfaceTime(dni2SurfaceTime(dni))
    output = output .. "<br/>"..os.date("ghdd",makeSurfaceTimeStamp(surface))
--    output = output .. "<br/>"..formatSurfaceTime(surface,args['format'])
--    output = output .. "<br/>"..makeSurfaceTimeStamp(surface)
--    output = output .. "<br/>"..lang:formatDate("c","@"..makeSurfaceTimeStamp(surface))


    return output
end

return p