Nicht angemeldeter Benutzer - Bearbeiten von Seiten ist nur als angemeldeter Benutzer möglich.

Änderungen

Zur Navigation springen Zur Suche springen
31.843 Bytes hinzugefügt ,  11:45, 18. Sep. 2020
K
1 Version importiert: Import der Vorlage Infobox Unternehmen aus der deutschsprachigen Wikipedia
Zeile 1: Zeile 1: −
--[=[ 2015-03-16
+
local DateTime  = { serial = "2020-08-30",
Date and time utilities
+
                    suite  = "DateTime",
]=]
+
                    item  = 20652535 }
 
+
-- Date and time objects
 
+
local Failsafe  = DateTime
 
+
local GlobalMod  = DateTime
-- local globals
+
local Calc      = { }
local DateTime
+
local Meta      = { }
 
local Parser    = { }
 
local Parser    = { }
 
local Private    = { }
 
local Private    = { }
 
local Prototypes = { }
 
local Prototypes = { }
 +
local Templates  = { }
 
local World      = { slang      = "en",
 
local World      = { slang      = "en",
 
                     monthsLong  = { },
 
                     monthsLong  = { },
Zeile 15: Zeile 16:  
                     months4    = { } }
 
                     months4    = { } }
 
local MaxYear    = 2099
 
local MaxYear    = 2099
local Nbsp      = mw.ustring.char( 160 )
+
local Frame
local Tab        = mw.ustring.char( 9 )
+
DateTime.char = { nbsp = mw.ustring.char( 160 ),
 +
                  tab  = mw.ustring.char( 9 ) }
 
World.era = { en = { "BC", "AD" } }
 
World.era = { en = { "BC", "AD" } }
 
World.monthsAbbr = {  en = { n = 3 }  }
 
World.monthsAbbr = {  en = { n = 3 }  }
Zeile 105: Zeile 107:  
     HST  = -1000    -- Hawaiian Standard Time
 
     HST  = -1000    -- Hawaiian Standard Time
 
}
 
}
 +
 +
 +
 +
local foreignModule = function ( access, advanced, append, alt, alert )
 +
    -- Fetch global module
 +
    -- Precondition:
 +
    --    access    -- string, with name of base module
 +
    --    advanced  -- true, for require(); else mw.loadData()
 +
    --    append    -- string, with subpage part, if any; or false
 +
    --    alt      -- number, of wikidata item of root; or false
 +
    --    alert    -- true, for throwing error on data problem
 +
    -- Postcondition:
 +
    --    Returns whatever, probably table
 +
    -- 2020-01-01
 +
    local storage = access
 +
    local fun, lucky, r
 +
    if advanced then
 +
        fun = require
 +
    else
 +
        fun = mw.loadData
 +
    end
 +
    if append then
 +
        storage = string.format( "%s/%s", storage, append )
 +
    end
 +
    lucky, r = pcall( fun,  "Module:" .. storage )
 +
    if not lucky then
 +
        local suited
 +
        GlobalMod.globalModules = GlobalMod.globalModules or { }
 +
        suited = GlobalMod.globalModules[ access ]
 +
        if not suited  and
 +
          type( alt ) == "number"  and
 +
          alt > 0 then
 +
            suited = string.format( "Q%d", alt )
 +
            suited = mw.wikibase.getSitelink( suited )
 +
            GlobalMod.globalModules[ access ] = suited or true
 +
        end
 +
        if type( suited ) == "string" then
 +
            storage = suited
 +
            if append then
 +
                storage = string.format( "%s/%s", storage, append )
 +
            end
 +
            lucky, r = pcall( fun, storage )
 +
        end
 +
        if not lucky and alert then
 +
            error( "Missing or invalid page: " .. storage )
 +
        end
 +
    end
 +
    return r
 +
end -- foreignModule()
      Zeile 116: Zeile 167:  
     return  mw.ustring.upper( mw.ustring.sub( a, 1, 1 ) )
 
     return  mw.ustring.upper( mw.ustring.sub( a, 1, 1 ) )
 
             .. mw.ustring.lower( mw.ustring.sub( a, 2 ) )
 
             .. mw.ustring.lower( mw.ustring.sub( a, 2 ) )
end -- fault()
+
end -- capitalize()
      Zeile 126: Zeile 177:  
     -- Returns:
 
     -- Returns:
 
     --    string, HTML span
 
     --    string, HTML span
     return string.format( "<span class=\"error\">%s</span>", a )
+
     local e = mw.html.create( "span" )
 +
                    :addClass( "error" )
 +
                    :wikitext( a )
 +
    return tostring( e )
 
end -- fault()
 
end -- fault()
         −
DateTime = function ( assign, alien )
+
local function frame()
     -- Create metatable (constructor)
+
    if not Frame then
 +
        Frame = mw.getCurrentFrame()
 +
    end
 +
    return Frame
 +
end -- frame()
 +
 
 +
 
 +
 
 +
Meta.localized  = false
 +
Meta.serial    = DateTime.serial
 +
Meta.signature  = "__datetime"
 +
Meta.suite      = "{DateTime}"
 +
Meta.components = { lang  = "string",
 +
                    bc    = "boolean",
 +
                    year  = "number",
 +
                    month = "number",
 +
                    week  = "number",
 +
                    dom  = "number",
 +
                    hour  = "number",
 +
                    min  = "number",
 +
                    sec  = "number",
 +
                    msec  = "number",
 +
                    mysec = "number",
 +
                    zone  = false,
 +
                    leap  = "boolean",
 +
                    jul  = "boolean" }
 +
Meta.order      = { "bc", "year", "month", "week", "dom",
 +
                    "hour", "min", "sec", "msec", "mysec" }
 +
Meta.tableI    = {    -- instance metatable
 +
    __index    = function ( self, access )
 +
                    local r = self[ Meta.signature ][ access ]
 +
                    if r == nil then
 +
                        if access == "serial" then
 +
                            r = Meta.serial
 +
                        elseif access == "suite" then
 +
                            r = "DateTime"
 +
                        else
 +
                            r = Prototypes[ access ]
 +
                        end
 +
                    end
 +
                    return r
 +
                end,
 +
    __newindex = function ( self, access, assign )
 +
                    if type( access ) == "string" then
 +
                        local data = self[ Meta.signature ]
 +
                        if assign == nil then
 +
                            local val = data[ access ]
 +
                            data[ access ] = nil
 +
                            if not Prototypes.fair( data ) then
 +
                                data[ access ] = val
 +
                            end
 +
                        elseif Prototypes.fair( data,
 +
                                                access,
 +
                                                assign ) then
 +
                            data[ access ] = assign
 +
                        end
 +
                    end
 +
                    return
 +
                end,
 +
    __add      = function ( op1, op2 )
 +
                    return Prototypes.future( op1, op2, true )
 +
                end,
 +
    __eq      = function ( op1, op2 )
 +
                    return Prototypes.flow( op1, op2, "eq" )
 +
                end,
 +
    __lt      = function ( op1, op2 )
 +
                    return Prototypes.flow( op1, op2, "lt" )
 +
                end,
 +
    __le      = function ( op1, op2 )
 +
                    return Prototypes.flow( op1, op2, "le" )
 +
                end,
 +
    __tostring = function ( e )
 +
                    return Prototypes.tostring( e )
 +
                end,
 +
    __call    = function ( func, ... )
 +
                    return Meta.fiat( ... )
 +
                end
 +
} -- Meta.tableI
 +
Meta.tableL    = {    -- library metatable
 +
    __index    = function ( self, access )
 +
                    local r
 +
                    if access == "serial" then
 +
                        r = Meta.serial
 +
                    elseif access == "suite" then
 +
                        r = Meta.suite
 +
                    end
 +
                    return r
 +
                end,
 +
    __newindex = function ()
 +
                    return
 +
                end,
 +
    __tostring = function ()
 +
                    return Meta.suite
 +
                end,
 +
    __call    = function ( func, ... )
 +
                    return Meta.fiat( ... )
 +
                end
 +
} -- Meta.tableL
 +
Meta.fiat = function ( assign, alien, add )
 +
     -- Create instance object (constructor)
 
     -- Parameter:
 
     -- Parameter:
 
     --    assign  -- string, with initial timestamp, or nil
 
     --    assign  -- string, with initial timestamp, or nil
 
     --                nil    -- now
 
     --                nil    -- now
 
     --                false  -- empty object
 
     --                false  -- empty object
 +
    --                table  -- clone this object, or copy from raw
 +
    --                          ignore remaining parameters
 
     --    alien  -- string, with language code, or nil
 
     --    alien  -- string, with language code, or nil
 +
    --    add    -- string, with interval (PHP strtotime), or nil
 
     -- Returns:
 
     -- Returns:
 
     --    table, as DateTime object
 
     --    table, as DateTime object
Zeile 143: Zeile 299:  
     local r
 
     local r
 
     Private.foreign()
 
     Private.foreign()
     r = Private.factory( assign, alien )
+
     if type( assign ) == "table" then
 +
        if assign.suite == Meta.suite  and
 +
          getmetatable( assign ) == Meta.tableI then
 +
            r = assign[ Meta.signature ]
 +
        else
 +
            r = Private.from( assign )
 +
        end
 +
    else
 +
        r = Private.factory( assign, alien, add )
 +
    end
 
     if type( r ) == "table" then
 
     if type( r ) == "table" then
         local meta = { }
+
         r = { [ Meta.signature ] = r }
        local s    = "__datetime"
+
         setmetatable( r, Meta.tableI )
        meta.__index    = function( self, access )
  −
                              return self[ s ][ access ]
  −
                          end
  −
        meta.__newindex = function( self, access, assign )
  −
                              if type( access ) == "string" then
  −
                                  local data = self[ s ]
  −
                                  if assign == nil then
  −
                                      local val = data[ access ]
  −
                                      data[ access ] = nil
  −
                                      if not Prototypes.fair( data ) then
  −
                                          data[ access ] = val
  −
                                      end
  −
                                  elseif Prototypes.fair( data,
  −
                                                          access,
  −
                                                          assign ) then
  −
                                      data[ access ] = assign
  −
                                  end
  −
                              end
  −
                              return
  −
                          end
  −
        r              = { [ s ] = r }
  −
        r.fair          = function ( ... )
  −
                              return Prototypes.fair( ... )
  −
                          end
  −
        r.figure        = function ( ... )
  −
                              return Prototypes.figure( ... )
  −
                          end
  −
        r.first        = function ( ... )
  −
                              return Prototypes.first( ... )
  −
                          end
  −
        r.format        = function ( ... )
  −
                              return Prototypes.format( ... )
  −
                          end
  −
        r.full          = function ( ... )
  −
                              return Prototypes.full( ... )
  −
                          end
  −
         setmetatable( r, meta )
   
     end
 
     end
 
     return r
 
     return r
end -- DateTime()
+
end -- Meta.fiat()
 +
setmetatable( DateTime, Meta.tableL )
 +
DateTime.serial  = nil
 +
 
    +
Calc.months = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
      −
Parser.digitsHeading = function ( analyse, alone, amount, add )
+
 
     -- String analysis, if digits only or at least 4 digits heading
+
--  Calc.fast = function ( at )
 +
--      -- Quick scan of full ISO stamp
 +
--      -- Parameter:
 +
--      --    apply  -- string, ISO
 +
--      -- Returns:
 +
--      --    table, with numeric components
 +
--      local r = { }
 +
--      r.year  = tonumber( at:sub(  1, 4 ) )
 +
--      r.month = tonumber( at:sub(  6, 2 ) )
 +
--      r.dom  = tonumber( at:sub(  9, 2 ) )
 +
--      r.hour  = tonumber( at:sub( 12, 2 ) )
 +
--      r.min  = tonumber( at:sub( 14, 2 ) )
 +
--      r.sec  = tonumber( at:sub( 17, 2 ) )
 +
--      if at:sub( 19, 1 ) == "." then
 +
--          r.msec = tonumber( at:sub( 20, 3 ) )
 +
--          if #at > 22 then
 +
--              r.mysec = tonumber( at:sub( 23, 3 ) )
 +
--          end
 +
--      end
 +
--      return r
 +
--  end -- Calc.fast()
 +
 
 +
 
 +
 
 +
Calc.fair = function ( adjust )
 +
    -- Normalize numeric components
 +
    -- Parameter:
 +
    --     adjust  -- table, with raw numbers
 +
    local ranges = { year  = { min = -999,
 +
                              max = 9999 },
 +
                    month = { min =  1,
 +
                              max = 12,
 +
                              mod = 12 },
 +
                    dom  = { min =  1,
 +
                              max = 28 },
 +
                    hour  = { mod = 24 },
 +
                    min  = { mod = 60 },
 +
                    sec  = { mod = 60 },
 +
                    msec  = { mod = 1000 },
 +
                    mysec = { mod = 1000 } }
 +
    local m, max, min, move, n, range, s
 +
    for i = 10, 2, -1 do
 +
        s = Meta.order[ i ]
 +
        n = adjust[ s ]
 +
        if n or move then
 +
            range = ranges[ s ]
 +
            if range then
 +
                min = range.min or 0
 +
                max = range.max  or  ( range.mod - 1 )
 +
                if move then
 +
                    n    = ( n or 0 )  +  move
 +
                    move = false
 +
                end
 +
                if n < min  or  n > max then
 +
                    if range.mod then
 +
                        m    = n % range.mod
 +
                        move = ( n - m )  /  range.mod
 +
                        n    = min + m
 +
                    else    -- dom
 +
                        if adjust.month and adjust.year  and
 +
                          adjust.month >= 1  and
 +
                          adjust.month <= 12 and
 +
                          adjust.year > 1900 then
 +
                            if n > 0 then
 +
                                max = Calc.final( adjust )
 +
                                while n > max do
 +
                                    n = n - max
 +
                                    if adjust.month < 12 then
 +
                                        adjust.month = adjust.month + 1
 +
                                    else
 +
                                        adjust.month = 1
 +
                                        adjust.year  = adjust.year + 1
 +
                                    end
 +
                                    max = Calc.final( adjust )
 +
                                end    -- while n <= max
 +
                            else
 +
                                while n < 1 do
 +
                                    if adjust.month == 1 then
 +
                                        adjust.month = 12
 +
                                        adjust.year  = adjust.year - 1
 +
                                    else
 +
                                        adjust.month = adjust.month - 1
 +
                                    end
 +
                                    max = Calc.final( adjust )
 +
                                    n  = n + max
 +
                                end    -- while n < 1
 +
                            end
 +
                        end
 +
                    end
 +
                end
 +
                adjust[ s ] = n
 +
            end
 +
        end
 +
    end -- for i
 +
end -- Calc.fair()
 +
 
 +
 
 +
 
 +
Calc.final = function ( adjust )
 +
    -- Retrieve number of days in particular month
 
     -- Parameter:
 
     -- Parameter:
     --    analyse  -- string to be scanned, starting with digit
+
     --    adjust   -- table, with date specification
    --                digits only, else starting with exactly 4 digits
  −
    --    alone    -- true, if only digits
  −
    --    amount   -- number of heading digits
  −
    --    add      -- table, to be extended
   
     -- Returns:
 
     -- Returns:
     --    table, extended if parsed
+
     --    number, of days in month
    --    false, if invalid text format
+
     local r = Calc.months[ adjust.month ]
     local r = add
+
     if adjust.month == 2  and
     if alone then
+
      ( adjust.year % 4 ~= 0  or
         -- digits only
+
        adjust.year % 400 == 0 ) then
        if amount <= 4 then
+
         r = 28
            r.year = tonumber( analyse )
+
    end
        elseif n == 14 then
+
    return r
            -- timestamp
+
end -- Calc.final()
            r.year   = tonumber( analyse:sub( 1, 4 ) )
+
 
            r.month  = tonumber( analyse:sub( 5, 2 ) )
+
 
            r.dom    = tonumber( analyse:sub( 7, 2 ) )
+
 
            r.hour   = tonumber( analyse:sub( 9, 2 ) )
+
Calc.future = function ( add )
            r.min    = tonumber( analyse:sub( 11, 2 ) )
+
    -- Parse move interval
             r.sec    = tonumber( analyse:sub( 13, 2 ) )
+
    -- Parameter:
 +
    --    add  -- string, with GNU relative items
 +
    -- Returns:
 +
    --     table, with numeric components, or false
 +
    local r, token
 +
    local units = { year     = true,
 +
                    month    = true,
 +
                    fortnight = { slot = "dom", mult = 14 },
 +
                    week      = { slot = "dom", mult = 7 },
 +
                    dom      = true,
 +
                    hour      = true,
 +
                    min      = true,
 +
                    sec      = true }
 +
    local story = string.format( " %s ", add:lower() )
 +
                        :gsub( "%s+", " " )
 +
                        :gsub( " yesterday ", " -1 dom " )
 +
                        :gsub( " tomorrow ",   " 1 dom " )
 +
                        :gsub( "(%l)s ", "%1 " )
 +
                        :gsub( " day ",    " dom " )
 +
                        :gsub( " minute ", " min " )
 +
                        :gsub( " second ", " sec " )
 +
    local feed  = function ()
 +
                      local slice
 +
                      token, slice = story:match( "^( (%S+)) " )
 +
                      return slice
 +
                  end
 +
    local fed   = function ()
 +
                      story = story:sub( #token + 1 )
 +
                  end
 +
    local m, n, s, u
 +
    while true do
 +
        s = feed()
 +
        if s then
 +
            n = 1
 +
            if s:match( "^[+-]?%d+$" ) then
 +
                n = tonumber( s )
 +
                fed()
 +
                s = feed()
 +
             end
 +
            if s then
 +
                u = units[ s ]
 +
            end
 +
            if s and u then
 +
                fed()
 +
                if u ~= true then
 +
                    s = u.slot
 +
                    n = n * u.mult
 +
                end
 +
                if feed() == "ago" then
 +
                    if n > 0 then
 +
                        n = - n
 +
                    end
 +
                    fed()
 +
                end
 +
                r      = r  or  { }
 +
                r[ s ] = ( r[ s ] or 0 ) +  n
 +
            else
 +
                r = false
 +
                break    -- while true
 +
            end
 
         else
 
         else
             r = false
+
             break    -- while true
 
         end
 
         end
     elseif amount == 4 then
+
    end    -- while true
         local s, sep, sx = analyse:match( "^(%d+)([%-%.:Ww]?)(.*)$" )
+
    return r
 +
end -- Calc.future()
 +
 
 +
 
 +
 
 +
Parser.digitsHeading = function ( analyse, alone, amount, add )
 +
    -- String analysis, if digits only or at least 4 digits heading
 +
    -- Parameter:
 +
    --    analyse  -- string to be scanned, starting with digit
 +
    --                digits only, else starting with exactly 4 digits
 +
    --    alone    -- true, if only digits
 +
    --    amount  -- number of heading digits
 +
    --    add      -- table, to be extended
 +
    -- Returns:
 +
    --    table, extended if parsed
 +
    --    false, if invalid text format
 +
    local r = add
 +
    if alone then
 +
        -- digits only
 +
        if amount <= 4 then
 +
            r.year = tonumber( analyse )
 +
        elseif amount == 14 then
 +
            -- timestamp
 +
            r.year  = tonumber( analyse:sub(  1,  4 ) )
 +
            r.month  = tonumber( analyse:sub(  5,  6 ) )
 +
            r.dom    = tonumber( analyse:sub(  7,  8 ) )
 +
            r.hour  = tonumber( analyse:sub(  9, 10 ) )
 +
            r.min    = tonumber( analyse:sub( 11, 12 ) )
 +
            r.sec    = tonumber( analyse:sub( 13, 14 ) )
 +
        else
 +
            r = false
 +
        end
 +
     elseif amount == 4 then
 +
         local s, sep, sx = analyse:match( "^(%d+)([%-%.:Ww]?)(.*)$" )
 
         r.year = tonumber( s )
 
         r.year = tonumber( s )
 
         if sep == "-" then
 
         if sep == "-" then
Zeile 263: Zeile 582:  
         else
 
         else
 
             r = false
 
             r = false
 +
        end
 +
        if r then
 +
            r.iso = true
 
         end
 
         end
 
     elseif amount == 8 then
 
     elseif amount == 8 then
Zeile 283: Zeile 605:  
                         n      = n .. "00"
 
                         n      = n .. "00"
 
                         r.msec = tonumber( n:sub( 1, 3 ) )
 
                         r.msec = tonumber( n:sub( 1, 3 ) )
                         sz     = s
+
                        if #n >= 6 then
 +
                            r.mysec = tonumber( n:sub( 4, 6 ) )
 +
                        end
 +
                         sz = s
 
                     end
 
                     end
 
                 end
 
                 end
Zeile 461: Zeile 786:  
         rO = false
 
         rO = false
 
     end
 
     end
     if not rO then
+
     if rO then
 +
        rO.iso = true
 +
    else
 
         rS = false
 
         rS = false
 
     end
 
     end
Zeile 500: Zeile 827:  
                         n = #s2
 
                         n = #s2
 
                         if n <= 2  and  #s3 == 4 then
 
                         if n <= 2  and  #s3 == 4 then
                             rO.dom  = tonumber( n )
+
                             rO.dom  = tonumber( s2 )
 
                             rO.year = tonumber( s3 )
 
                             rO.year = tonumber( s3 )
 
                             rO.dom2 = ( n == 2 )
 
                             rO.dom2 = ( n == 2 )
Zeile 640: Zeile 967:  
                 s = sx:match( "^%.(%d+)$" )
 
                 s = sx:match( "^%.(%d+)$" )
 
                 if s then
 
                 if s then
                     r.msec = tonumber( s )
+
                    s  = s .. "00"
 +
                     r.msec = tonumber( s:sub( 1, 3 ) )
 +
                    if #s >= 6 then
 +
                        r.mysec = tonumber( s:sub( 4, 6 ) )
 +
                    end
 
                 else
 
                 else
 
                     r = false
 
                     r = false
Zeile 861: Zeile 1.192:       −
Private.factory = function ( assign, alien )
+
Private.factory = function ( assign, alien, add )
 
     -- Create DateTime table (constructor)
 
     -- Create DateTime table (constructor)
 
     -- Parameter:
 
     -- Parameter:
Zeile 868: Zeile 1.199:  
     --                false  -- empty object
 
     --                false  -- empty object
 
     --    alien  -- string, with language code, or nil
 
     --    alien  -- string, with language code, or nil
 +
    --    add    -- string, with interval (PHP strtotime), or nil
 
     -- Returns:
 
     -- Returns:
 
     --    table, for DateTime object
 
     --    table, for DateTime object
 
     --    string or false, if failed
 
     --    string or false, if failed
 
     local l    = true
 
     local l    = true
    local r    = false
   
     local slang = mw.text.trim( alien or World.slang or "en" )
 
     local slang = mw.text.trim( alien or World.slang or "en" )
 +
    local r
 
     if assign == false then
 
     if assign == false then
 
         r = { }
 
         r = { }
 
     else
 
     else
 
         local stamp = ( assign or "now" )
 
         local stamp = ( assign or "now" )
 +
        local shift
 +
        if add then
 +
            shift = Private.future( add )
 +
        end
 +
        r = false
 
         if stamp == "now" then
 
         if stamp == "now" then
             stamp = mw.getCurrentFrame():callParserFunction( "#timel",
+
             stamp = frame():callParserFunction( "#timel", "c", shift )
                                                            "c" )
+
            shift = false
 
         else
 
         else
 
             local seconds = stamp:match( "^#(%d+)$" )
 
             local seconds = stamp:match( "^#(%d+)$" )
Zeile 888: Zeile 1.225:  
             end
 
             end
 
         end
 
         end
         l, r = pcall( Private.fetch, stamp, slang )
+
         l, r = pcall( Private.fetch, stamp, slang, shift )
 
     end
 
     end
 
     if l  and  type( r ) == "table" then
 
     if l  and  type( r ) == "table" then
Zeile 900: Zeile 1.237:       −
Private.fetch = function ( analyse, alien )
+
Private.fetch = function ( analyse, alien, add )
 
     -- Retrieve object from string
 
     -- Retrieve object from string
 
     -- Parameter:
 
     -- Parameter:
 
     --    analyse  -- string to be interpreted
 
     --    analyse  -- string to be interpreted
 
     --    alien    -- string with language code, or nil
 
     --    alien    -- string with language code, or nil
 +
    --    add      -- table, with interval, or nil
 
     -- Returns:
 
     -- Returns:
 
     --    table, if parsed
 
     --    table, if parsed
Zeile 911: Zeile 1.249:  
     local r
 
     local r
 
     if type( analyse ) == "string" then
 
     if type( analyse ) == "string" then
 +
        local strip = mw.ustring.char( 0x5B, 0x200E, 0x200F, 0x5D )
 
         r =  analyse:gsub( "&nbsp;", " " )
 
         r =  analyse:gsub( "&nbsp;", " " )
 
                     :gsub( "&#160;", " " )
 
                     :gsub( "&#160;", " " )
 
                     :gsub( "&#x[aA]0;", " " )
 
                     :gsub( "&#x[aA]0;", " " )
 
                     :gsub( "&#32;", " " )
 
                     :gsub( "&#32;", " " )
                     :gsub( Nbsp, " " )
+
                     :gsub( DateTime.char.nbsp, " " )
                     :gsub( Tab, " " )
+
                     :gsub( DateTime.char.tab, " " )
 
                     :gsub( "  +", " " )
 
                     :gsub( "  +", " " )
 
                     :gsub( "%[%[", "" )
 
                     :gsub( "%[%[", "" )
 
                     :gsub( "%]%]", "" )
 
                     :gsub( "%]%]", "" )
 +
                    :gsub( strip, "" )
 
         r = mw.text.trim( r )
 
         r = mw.text.trim( r )
 
         if r == "" then
 
         if r == "" then
 
             r = { }
 
             r = { }
 
         else
 
         else
             local slang = ( alien or "" )
+
             local slang = ( alien or "" )
 +
            local parser = { en  = "GermanEnglish",
 +
                            de  = "GermanEnglish",
 +
                            frr = "GermanEnglish",
 +
                            nds = "GermanEnglish" }
 +
            local suitable
 
             if slang == "" then
 
             if slang == "" then
 
                 slang = "en"
 
                 slang = "en"
Zeile 933: Zeile 1.278:  
                 end
 
                 end
 
             end
 
             end
             slang = slang:lower()
+
             slang   = slang:lower()
             if slang == "en" or slang == "de" then
+
             suitable = parser[ slang ]
 +
            if suitable then
 
                 local l
 
                 local l
                 l, r = pcall( Parser.GermanEnglish, r )
+
                 l, r = pcall( Parser[ suitable ], r )
 
                 if l and r then
 
                 if l and r then
 
                     if not Prototypes.fair( r ) then
 
                     if not Prototypes.fair( r ) then
 
                         r = false
 
                         r = false
 +
                    elseif add then
 +
                        r = Prototypes.future( r, add )
 
                     end
 
                     end
 +
                else
 +
                    r = "invalid format"
 
                 end
 
                 end
 
             else
 
             else
                 r = "unknown language"
+
                 r = "unknown language: " .. slang
 
             end
 
             end
 
         end
 
         end
Zeile 954: Zeile 1.304:       −
Private.foreign = function ()
+
Private.field = function ( at, ask, adapt, atleast )
     -- Retrieve localization submodule
+
     -- Format object as string
     if not World.localization then
+
    -- Parameter:
        local l, d = pcall( mw.loadData, "Module:DateTime/local" )
+
    --    at      -- DateTime
         if l then
+
    --    ask      -- string, with format spec, or nil
            local wk
+
    --    adapt    -- table, with options, or nil
             if d.slang then
+
     --                .lang    -- string, with particular language code
                 World.slang = d.slang
+
    --                .london  -- true: UTC output; default: local
            end
+
    --                .lonely  -- true: permit lonely hour
            for k, v in pairs( d ) do
+
    --    atleast  -- string, with default value, or nil
                wk = World[ k ]
+
    -- Returns:
                 if wk  and  wk.en then
+
    --    string, or false, if invalid, or number for julian date
                     for subk, subv in pairs( v ) do
+
    local r, spec
                        wk[ subk ] = subv
+
    if type( ask ) == "string" then
                    end -- for k, v
+
         if ask:sub( 1, 1 ) == "$" then
 +
             if ask:sub( 1, 11 ) == "$JulianDate" then
 +
                 local luxury = ( ask:sub( -2 ) == ",$" )
 +
                 if ask:sub( 1, 14 ) == "$JulianDateJul" then
 +
                     at.legacy = true
 +
                elseif ask:sub( 1, 15 ) == "$JulianDateGreg" then
 
                 else
 
                 else
                     World[ k ] = v
+
                     at.legacy = Private.former( at )
 
                 end
 
                 end
             end -- for k, v
+
                r = Private.fixed( at, luxury )
 +
            elseif ask:sub( 1, 11 ) == "$JulianCal$" then
 +
                adapt.legacy = true
 +
                spec = ask:sub( 12 )
 +
            elseif ask:sub( 1, 3 ) == "$\"$" then
 +
                r = ask:sub( 4 )
 +
            else
 +
                spec = ask
 +
             end
 +
        else
 +
            spec = ask
 
         end
 
         end
         World.localization = true
+
    else
 +
         spec = false
 
     end
 
     end
end -- Private.foreign()
+
    if not r then
 +
        r = Private.format( at, spec, adapt )
 +
    end
 +
    return r or atleast
 +
end -- Private.field()
         −
Prototypes.fair = function ( self, access, assign )
+
Private.fixed = function ( at, advanced )
     -- Check formal validity of table
+
     -- Compute julian date
 
     -- Parameter:
 
     -- Parameter:
     --    self    -- table, to be checked
+
     --    at        -- DateTime
     --     access -- string or nil, single item to be checked
+
     --                 .legacy -- true: at is in Julian calendar
     --    assign -- single access value to be checked
+
     --    advanced -- true: format long number
 
     -- Returns:
 
     -- Returns:
     --    true, if valid;  false, if not
+
     --    number, or string
     local r = ( type( self ) == "table" )
+
     local mM, mMY, mY, nY, r
     if r then
+
     if at.year then
         local defs = { year = { max = MaxYear },
+
         mY = at.year * 12
                      month = { min = 1,
+
    else    -- actually invalid
                                max = 12 },
+
        mY = 0
                      dom   = { min =  1,
+
    end
                                max = 31 },
+
    if at.month then
                      hour = { max = 23 },
+
        mMY = at.month
                      min   = { max = 59 },
+
    else
                      sec   = { max = 61 },
+
        mMY = 1
                      msec = { max = 1000 }
+
    end
        }
+
    mMY = mMY + 57609
         local months = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+
    if at.dom then
         local fNum =
+
        r = at.dom
             function ( k, v )
+
    else
                local ret = true
+
        r = 1
                local dk  = defs[ k ]
+
    end
                if dk then
+
    mM = ( mY + mMY ) *  0.08333333333    -- divided by 12 months
                    if type( dk.max ) == "number" then
+
    nY = math.floor( mM - 1 )
                        ret = ( type( v ) == "number" )
+
    r  = math.floor( nY * 365.25 )
                        if ret then
+
        + math.floor( ( mMY%12 + 4 )  * 30.6 )
                            local min
+
        + r
                            if dk.min then
+
        if at.legacy then
                                min = dk.min
+
            r = r - 32205.5
                            else
+
        else
                                min = 0
+
            r = r - math.floor( nY * 0.01 )    -- no leap day in century
                            end
+
                  + math.floor( nY * 0.0025 )   -- but every 400 years
                            ret = ( v >= min  and v <= dk.max
+
                  - 32167.5
                                    and  math.floor( v ) == v )
+
        end
                            if ret and dk.f then
+
    if at.hour then   -- divided by 24 hours per day
                                ret = dk.f( v )
+
        r = r  +  at.hour * 0.0416666666666667
                            end
+
    else
                         end
+
        r = r + 0.5
 +
    end
 +
    if at.min then    -- divided by 1440 minutes per day
 +
        r = r  + at.min * 0.000694444444
 +
    end
 +
    if at.sec then    -- divided by 86400 seconds per day
 +
        r = r  +  at.min * 0.00001157407407
 +
    end
 +
    if at.bc then
 +
         r = 3442406 - r
 +
         if at.legacy then
 +
             r = r + 3
 +
        end
 +
    end
 +
    if advanced then
 +
        local slang = ( at.lang or World.slang )
 +
        local o = mw.language.new( slang )
 +
        r = o:formatNum( r )
 +
    end
 +
    return r
 +
end -- Private.fixed()
 +
 
 +
 
 +
 
 +
Private.flow = function ( at1, at2 )
 +
    -- Compare two objects
 +
    -- Parameter:
 +
    --    at1  -- DateTime
 +
    --    at2  -- DateTime
 +
    -- Returns:
 +
    --    -1, 0, 1 or nil if not comparable
 +
    local r = 0
 +
    if at1.bc or at2.bc  and  at1.bc ~= at2.bc then
 +
        if at1.bc then
 +
            r = -1
 +
        else
 +
            r = 1
 +
        end
 +
    else
 +
        local life  = false
 +
        local s, v1, v2
 +
        for i = 2, 10 do
 +
            s = Meta.order[ i ]
 +
            v1 = at1[ s ]
 +
            v2 = at2[ s ]
 +
            if v1 or v2 then
 +
                if v1 and v2 then
 +
                    if v1 < v2 then
 +
                        r = -1
 +
                    elseif v1 > v2 then
 +
                        r = 1
 +
                    end
 +
                elseif life then
 +
                    if v2 then
 +
                        r = -1
 +
                    else
 +
                         r = 1
 
                     end
 
                     end
 +
                else
 +
                    r = nil
 
                 end
 
                 end
                 return ret
+
                 if r ~= 0 then
            end -- fNum()
+
                    if at1.bc and r then
        defs.dom.f =
+
                        r = r * -1
            function ()
+
                    end
                local ret
+
                     break    -- for i
                local d
  −
                if access == "dom" then
  −
                    d = assign
  −
                else
  −
                     d = self.dom
   
                 end
 
                 end
                 if d then
+
                 life = true
                    ret = ( d <= 28 )
+
            end
                    if not ret then
+
        end -- for i
                        local m
+
    end
                        if access == "month" then
+
    return r
                            m = assign
+
end -- Private.flow()
                        else
+
 
                            m = self.month
+
 
                        end
+
 
                        if m then
+
Private.foreign = function ()
                            ret = ( d <= months[ m ] )
+
    -- Retrieve localization submodule
                            if ret then
+
    if not Meta.localized then
                                local y
+
        local d = foreignModule( DateTime.suite,
                                if access == "year" then
+
                                false,
                                    y = assign
+
                                "local",
                                else
+
                                DateTime.item )
                                    y = self.year
+
        if type( d ) == "table" then
                                end
+
            local wk
                                if d == 29  and  m == 2  and  y then
+
            if d.slang then
                                    if y % 4 ~= 0 or y % 400 == 0 then
+
                Meta.suite  = string.format( "%s %s",
                                        ret = false
+
                                            Meta.suite, d.slang )
                                    end
+
                World.slang = d.slang
                                end
+
            end
                            end
+
            for k, v in pairs( d ) do
                         end
+
                wk = World[ k ]
                     end
+
                if wk and wk.en then
 +
                    for subk, subv in pairs( v ) do
 +
                         wk[ subk ] = subv
 +
                     end -- for k, v
 
                 else
 
                 else
                     ret = true
+
                     World[ k ] = v
 
                 end
 
                 end
                return ret
+
            end -- for k, v
            end -- defs.dom.f()
+
        end
         defs.sec.f =
+
        Meta.localized = true
             function ()
+
    end
                 local ret
+
end -- Private.foreign()
                 local second
+
 
                 if access == "sec" then
+
 
                    second = assign
+
 
                 else
+
Private.format = function ( at, ask, adapt )
                     second = self.sec
+
    -- Format object as string
 +
    -- Parameter:
 +
    --    at    -- table, with numbers etc.
 +
    --    ask    -- string, format spec, or nil
 +
    --    adapt  -- table, with options, or nil
 +
    --              .lang    -- string, with particular language code
 +
    --              .london  -- true: UTC output; default: local
 +
    --              .lonely  -- true: permit lonely hour
 +
    -- Returns:
 +
    --    string, or not
 +
    local slang = at.lang or "en"
 +
    local opts  = { lang = slang }
 +
    local babel, r
 +
    if type( adapt ) == "table" then
 +
         if type( adapt.lang ) == "string" then
 +
            local i = adapt.lang:find( "-", 3, true )
 +
             if i then
 +
                slang = adapt.lang:lower()
 +
                 opts.lang = slang:sub( 1,  i - 1 )
 +
            else
 +
                 opts.lang = adapt.lang:lower()
 +
            end
 +
        end
 +
        opts.london = adapt.london
 +
        opts.lonely = adapt.lonely
 +
    end
 +
    babel = mw.language.new( opts.lang:lower() )
 +
    if babel then
 +
        local shift, show, stamp, suffix, limit4, locally
 +
        if at.month then
 +
            stamp = World.monthsLong.en[ at.month ]
 +
            if at.year then
 +
                 stamp = string.format( "%s %04d", stamp, at.year )
 +
            end
 +
            if at.dom then
 +
                stamp = string.format( "%d %s", at.dom, stamp )
 +
            end
 +
            if ask and ask:find( "Mon4", 1, true ) then
 +
                local mon4 = World.months4[ opts.lang:lower() ]
 +
                 if mon4  and  mon4[ at.month ] then
 +
                     limit4 = true
 
                 end
 
                 end
                 if second then
+
            end
                     ret = ( second <= 59 )
+
        elseif at.year then
                     if not ret and self.leap then
+
            stamp = string.format( "%04d", at.year )
                         ret = true
+
        end
 +
        if at.hour then
 +
            if stamp then
 +
                 stamp = stamp .. " "
 +
            else
 +
                stamp = ""
 +
            end
 +
            stamp = string.format( "%s%02d:", stamp, at.hour )
 +
            if at.min then
 +
                stamp = string.format( "%s%02d", stamp, at.min )
 +
                if at.sec then
 +
                     stamp = string.format( "%s:%02d",
 +
                                          stamp, at.sec )
 +
                     if at.msec then
 +
                         stamp = string.format( "%s.%03d",
 +
                                              stamp, at.msec )
 +
                        if at.mysec then
 +
                            stamp = string.format( "%s%03d",
 +
                                                  stamp,
 +
                                                  at.mysec )
 +
                        end
 
                     end
 
                     end
 
                 end
 
                 end
                 return ret
+
            else
             end -- defs.sec.f()
+
                 stamp = stamp .. "00"
         if access or assign then
+
             end
             r = ( type( access ) == "string" )
+
            if at.zone then
             if r then
+
                stamp = stamp .. World.zones.formatter( at, "+-" )
                 local def = defs[ access ]
+
            end
                 if def then
+
        end
                     r = fNum( access, assign )
+
        show, suffix = World.templates.formatter( at, ask, opts )
                     if r then
+
         if limit4 then
                         if def == "dom" or
+
             show = show:gsub( "M", "F" )
                          def == "month" or
+
        end
                          def == "year" then
+
        if type( opts.london ) == "boolean" then
                             r = defs.dom.f()
+
            locally = not opts.london
 +
        else
 +
            locally = true
 +
        end
 +
        r = babel:formatDate( show, stamp, locally )
 +
        r = r:gsub( "&#160;$", "" )
 +
        if at.year and at.year < 1000 then
 +
            r = r:gsub( string.format( "%04d", at.year ),
 +
                        tostring( at.year ) )
 +
        end
 +
        if at.month then
 +
            local bucket, m, suite, x
 +
            if show:find( "F", 1, true ) then
 +
                suite = "monthsLong"
 +
            elseif show:find( "M", 1, true ) then
 +
                suite = "monthsAbbr"
 +
            end
 +
            bucket = World[ suite ]
 +
             if bucket then
 +
                 m = bucket[ opts.lang:lower() ]
 +
                 if slang then
 +
                     x = bucket[ slang:lower() ]
 +
                end
 +
                if m then
 +
                    local base = m[ at.month ]
 +
                    local ex
 +
                     if x then
 +
                         ex = x[ at.month ]
 +
                    end
 +
                    if suite == "monthsAbbr" then
 +
                        local stop
 +
                        if ex then
 +
                            stop = x.suffix
 +
                            base = ex
 +
                        else
 +
                            stop = m.suffix
 +
                        end
 +
                        if base and stop then
 +
                            local shift, std
 +
                            std  = string.format( "%s%%%s",
 +
                                                  base[ 1 ], stop )
 +
                            shift = string.format( "%s%s",
 +
                                                  base[ 2 ], stop )
 +
                            r = mw.ustring.gsub( r, std, shift )
 +
                        end
 +
                    elseif suite == "monthsLong" then
 +
                        if base and ex then
 +
                             r = mw.ustring.gsub( r, base, ex )
 
                         end
 
                         end
 
                     end
 
                     end
                elseif access == "lang" then
  −
                    r = ( type( assign ) == "string" )
  −
                    if r then
  −
                        r = assign:match( "^%l%l%l?-?%a*$" )
  −
                    end
  −
                elseif access == "london" then
  −
                    r = ( type( assign ) == "boolean" )
   
                 end
 
                 end
 
             end
 
             end
         else
+
         end
            local order = { "bc", "year", "month", "dom",
+
        if suffix then
                            "hour", "min", "sec", "msec" }
+
            r = r .. suffix
            local life = false
  −
            local leak = false
  −
            local s, v
  −
            for i = 1, 8 do
  −
                s = order[ i ]
  −
                v = self[ s ]
  −
                if v then
  −
                    if not life and leak then
  −
                        -- gap detected
  −
                        r = false
  −
                        break
  −
                    else
  −
                        if not fNum( s, v ) then
  −
                            r = false
  −
                            break
  −
                        end
  −
                        life = true
  −
                        leak = true
  −
                    end
  −
                else
  −
                    life = false
  −
                end
  −
            end -- for i
   
         end
 
         end
 
     end
 
     end
 
     return r
 
     return r
end -- Prototypes.fair()
+
end -- Private.format()
         −
Prototypes.figure = function ( self, assign )
+
Private.former = function ( at )
     -- Assign month by name
+
     -- Analyze whether Julian calendar
 
     -- Parameter:
 
     -- Parameter:
     --    self    -- table, to be filled
+
     --    at  -- table, to be evaluated
     --    assign -- string, with month name
+
    -- Returns:
 +
    --    true, i
 +
    local r
 +
    if at.year then
 +
        if at.year < 1582 then
 +
            r = true
 +
        elseif at.year == 1582 then
 +
            if at.month then
 +
                if at.month < 10 then
 +
                    r = true
 +
                elseif at.month == 10 then
 +
                    r = ( at.dom <= 15 )
 +
                end
 +
            end
 +
        end
 +
    end
 +
     return r
 +
end -- Private.former()
 +
 
 +
 
 +
 
 +
Private.from = function ( attempt )
 +
     -- Create valid raw table from arbitrary table
 +
    -- Parameter:
 +
    --    attempt -- table, to be evaluated
 
     -- Returns:
 
     -- Returns:
     --    number 1...12, if valid; false, if not
+
     --    table, with valid components, or nil
     local r = false
+
    local data = { }
     if type( self ) == "table" and  type( assign ) == "string" then
+
     local r
         r = Parser.monthNumber( assign )
+
     for k, v in pairs( Meta.components ) do
         if r then
+
        if v then
             self.month = r
+
            v = ( type( attempt[ k ] ) ==  v )
 +
        else
 +
            v = true
 +
         end
 +
         if v then
 +
             data[ k ] = attempt[ k ]
 
         end
 
         end
 +
    end -- for k, v
 +
    if Prototypes.fair( data ) then
 +
        r = data
 
     end
 
     end
 
     return r
 
     return r
end -- Prototypes.figure()
+
end -- Private.from()
         −
Prototypes.first = function ( self )
+
Private.future = function ( add )
     -- Retrieve abbreviated month name in current language
+
     -- Normalize move interval
 
     -- Parameter:
 
     -- Parameter:
     --    self  -- table, to be evaluated
+
     --    add  -- string or number, to be added
 
     -- Returns:
 
     -- Returns:
     --    string, if defined;  false, if not
+
     --    table, with shift, or false/nil
 
     local r
 
     local r
     if type( self ) == "table"  and  self.month then
+
     if add then
         local slang = ( self.lang or World.slang )
+
        local s = type( add )
         r = World.monthsLong[ slang ]
+
        if s == "string"  and  add:match( "^%s*[+-]?%d+%.?%d*%s*$" ) then
 +
            r = tonumber( add )
 +
            s = "number"
 +
        end
 +
         if s == "number" then
 +
            if r == 0 then
 +
                r = false
 +
            else
 +
                r = string.format( "%d second",  r or add )
 +
            end
 +
        elseif s == "string" then
 +
            r = add
 +
         else
 +
            r = false
 +
        end
 
         if r then
 
         if r then
             local brief = World.monthsAbbr[ slang ]
+
             r = Calc.future( r )
            r = r[ self.month ]
  −
            if brief then
  −
                local ex = brief[ self.month ]
  −
                local s  = brief.suffix
  −
                if ex then
  −
                    r = ex[ 2 ]
  −
                else
  −
                    local n = brief.n or 3
  −
                    r = mw.ustring.sub( r, 1, n )
  −
                end
  −
                if s then
  −
                    r = r .. s
  −
                end
  −
            end
   
         end
 
         end
    else
  −
        r = false
   
     end
 
     end
 
     return r
 
     return r
end -- Prototypes.first()
+
end -- Private.future()
         −
Prototypes.format = function ( self, ask, adapt )
+
Prototypes.clone = function ( self )
     -- Format object as string
+
     -- Clone object
 
     -- Parameter:
 
     -- Parameter:
     --    self   -- table, with numbers etc.
+
     --    self  -- table, with object, to be cloned
    --    ask    -- string, format spec, or nil
  −
    --    adapt -- table, with options, or nil
  −
    --              .lang    -- string, with particular language code
  −
    --              .lonely  -- true: permit lonely hour
   
     -- Returns:
 
     -- Returns:
     --    string, or false, if invalid
+
     --    table, with object
     local r = false
+
    local r = { [ Meta.signature ] = self[ Meta.signature ] }
     if type( self ) == "table" then
+
    setmetatable( r, Meta.tableI )
         local opts  = { lang = self.lang }
+
    return r
         local babel, slang
+
end -- Prototypes.clone()
         if type( adapt ) == "table" then
+
 
             if type( adapt.lang ) == "string" then
+
 
                local i = adapt.lang:find( "-", 3, true )
+
 
                if i then
+
Prototypes.failsafe = function ( self, atleast )
                    slang = adapt.lang
+
    -- Retrieve versioning and check for compliance
                    opts.lang = slang:sub( 1, i - 1 )
+
    -- Precondition:
                else
+
    --    self    -- table, or not, with DateTime object, unused
                    opts.lang = adapt.lang
+
    --    atleast  -- string, with required version
 +
    --                        or "wikidata" or "~" or "@" or false
 +
    -- Postcondition:
 +
    --    Returns  string  -- with queried version/item, also if problem
 +
    --              false  -- if appropriate
 +
    -- 2020-08-17
 +
     local since = atleast
 +
    local last    = ( since == "~" )
 +
     local linked  = ( since == "@" )
 +
    local link    = ( since == "item" )
 +
    local r
 +
    if last  or  link  or  linked  or  since == "wikidata" then
 +
         local item = Meta.item
 +
         since = false
 +
         if type( item ) == "number" and  item > 0 then
 +
            local suited = string.format( "Q%d", item )
 +
             if linkedlink then
 +
                r = suited
 +
            else
 +
                local entity = mw.wikibase.getEntity( suited )
 +
                if type( entity ) == "table" then
 +
                    local seek = Failsafe.serialProperty or "P348"
 +
                    local vsn  = entity:formatPropertyValues( seek )
 +
                    if type( vsn ) == "table" and
 +
                      type( vsn.value ) == "string"  and
 +
                      vsn.value ~= "" then
 +
                        if last  and
 +
                          vsn.value == ( Meta.serial or
 +
                                          DateTime.serial ) then
 +
                            r = false
 +
                        elseif linked then
 +
                            if mw.title.getCurrentTitle().prefixedText
 +
                              == mw.wikibase.getSitelink( suited ) then
 +
                                r = false
 +
                            else
 +
                                r = suited
 +
                            end
 +
                        else
 +
                            r = vsn.value
 +
                        end
 +
                        if last then
 +
                            r = false
 +
                        else
 +
                            r = vsn.value
 +
                        end
 +
                    end
 
                 end
 
                 end
 
             end
 
             end
            opts.lang  = opts.lang:lower()
  −
            opts.london = adapt.london
  −
            opts.lonely = adapt.lonely
   
         end
 
         end
        babel = mw.language.new( opts.lang )
+
    end
        if babel then
+
    if type( r ) == "nil" then
            local shift, show, stamp, suffix, limit4, locally
+
        if not since  or  since <= Meta.serial then
            if self.month then
+
             r = Meta.serial
                stamp = World.monthsLong.en[ self.month ]
+
        else
                if self.year then
+
             r = false
                    stamp = string.format( "%s %04d", stamp, self.year )
+
         end
                end
+
     end
                if self.dom then
+
     return r
                    stamp = string.format( "%d %s", self.dom, stamp )
+
end -- Prototypes.failsafe()
                end
+
 
                if ask and ask:find( "Mon4" ) then
+
 
                    local mon4 = World.months4[ opts.lang ]
+
 
                    if mon4 then
+
Prototypes.fair = function ( self, access, assign )
                        if mon4[ self.month ] then
+
     -- Check formal validity of table
                            limit4 = true
+
     -- Parameter:
                        end
+
     --    self   -- table, to be checked
                    end
+
    --    access -- string or nil, single item to be checked
                end
+
    --    assign  -- single access value to be checked
            elseif self.year then
  −
                stamp = string.format( "%04d", self.year )
  −
            end
  −
            if self.hour then
  −
                stamp = string.format( "%s %02d:", stamp, self.hour )
  −
                if self.min then
  −
                    stamp = string.format( "%s%02d", stamp, self.min )
  −
                    if self.sec then
  −
                        stamp = string.format( "%s:%02d",
  −
                                              stamp, self.sec )
  −
                        if self.msec then
  −
                            stamp = string.format( "%s.%d",
  −
                                                  stamp, self.msec )
  −
                        end
  −
                    end
  −
                else
  −
                    stamp = stamp .. "00"
  −
                end
  −
                if self.zone then
  −
                    stamp = stamp .. World.zones.formatter( self, "+-" )
  −
                end
  −
            end
  −
            show, suffix = World.templates.formatter( self, ask, opts )
  −
            if limit4 then
  −
                show = show:gsub( "M", "F" )
  −
            end
  −
            if type( opts.london ) == "boolean" then
  −
                locally = not opts.london
  −
            else
  −
                locally = true
  −
            end
  −
             r = babel:formatDate( show, stamp, locally )
  −
            r = r:gsub( "&#160;$", "" )
  −
            if self.year and self.year < 1000 then
  −
                r = r:gsub( string.format( "%04d", self.year ),
  −
                            tostring( self.year ) )
  −
            end
  −
            if self.month then
  −
                local bucket, m, suite, x
  −
                if show:find( "F" ) then
  −
                    suite = "monthsLong"
  −
                elseif show:find( "M" ) then
  −
                    suite = "monthsAbbr"
  −
                end
  −
                bucket = World[ suite ]
  −
                if bucket then
  −
                    m = bucket[ opts.lang ]
  −
                    if slang then
  −
                        x = bucket[ slang ]
  −
                    end
  −
                    if m then
  −
                        local base = m[ self.month ]
  −
                        local ex
  −
                        if x then
  −
                            ex = x[ self.month ]
  −
                        end
  −
                        if suite == "monthsAbbr" then
  −
                            local stop
  −
                            if ex then
  −
                                stop = x.suffix
  −
                                base = ex
  −
                            else
  −
                                stop = m.suffix
  −
                            end
  −
                            if base and stop then
  −
                                local shift, std
  −
                                std  = string.format( "%s%%%s",
  −
                                                      base[ 1 ], stop )
  −
                                shift = string.format( "%s%s",
  −
                                                      base[ 2 ], stop )
  −
                                r = mw.ustring.gsub( r, std, shift )
  −
                            end
  −
                        elseif suite == "monthsLong" then
  −
                            if base and ex then
  −
                                r = mw.ustring.gsub( r, base, ex )
  −
                            end
  −
                        end
  −
                    end
  −
                end
  −
            end
  −
             if suffix then
  −
                r = r .. suffix
  −
            end
  −
         end
  −
     end
  −
     return r
  −
end -- Prototypes.format()
  −
 
  −
 
  −
 
  −
Prototypes.full = function ( self )
  −
     -- Retrieve month name in current language
  −
     -- Parameter:
  −
     --    self  -- table, to be evaluated
   
     -- Returns:
 
     -- Returns:
     --    string, if defined;  false, if not
+
     --    true, if valid;  false, if not
     local r
+
     local r = ( type( self ) == "table" )
    if type( self ) == "table" and  self.month then
+
    if r then
         local slang = ( self.lang or World.slang )
+
         local defs = { year  = { max = MaxYear },
        r = World.monthsLong[ slang ]
+
                      month = { min 1,
        if r then
+
                                max = 12 },
            r = r[ self.month ]
+
                      week  = { min = 1,
        end
+
                                max = 53 },
    else
+
                      dom  = { min =  1,
        r = false
+
                                max = 31 },
    end
+
                      hour  = { max = 23 },
    return r
+
                      min  = { max = 59 },
end -- Prototypes.full()
+
                      sec  = { max = 61 },
 
+
                      msec = { max = 999 },
 
+
                      mysec = { max = 999 }
 
+
        }
World.templates.formatter function ( assigned, ask, adapt )
+
         local fNum =
    -- Retrieve format specification string
+
             function ( k, v )
    -- Parameter:
+
                local ret = true
    --    assigned -- table, with numbers etc.
+
                 local dk  = defs[ k ]
    --    ask      -- string, format spec, or nil
+
                if dk then
    --    adapt    -- table, with options
+
                    if type( dk.max ) == "number" then
    --                  .lang    -- string, with particular language code
+
                        ret = ( type( v ) == "number" )
    --                  .lonely  -- true: permit lonely hour
+
                        if ret then
    -- Returns:
+
                            local min
    --    1 -- string
+
                            if dk.min then
    --    2  -- string or nil; append suffix (zone)
+
                                min = dk.min
    local r1, r2
+
                            else
    if not ask  or ask == "" then
+
                                min = 0
        r1 = "c"
+
                            end
    else
+
                            ret = ( v >= min  and  v <= dk.max
         local template = World.templates[ ask ]
+
                                    and  math.floor( v ) == v )
        r1 = ask
+
                            if ret and dk.f then
        if not template then
+
                                ret = dk.f( v )
             local slang = ( adapt.lang or assigned.lang or World.slang )
+
                            end
            local tmp  = World.templates[ slang ]
+
                        end
            if tmp then
  −
                 template = tmp[ ask ]
  −
            end
  −
        end
  −
        if type( template ) == "table" then
  −
            local low = ( ask == "ISO" or ask == "ISO-T" )
  −
            r1 = template.spec
  −
            if assigned.year then
  −
                if not assigned.dom then
  −
                    r1 = r1:gsub( "[ .%-]?[dDjlNwz][ .,%-]*", "" )
  −
                          :gsub( "^&#160;", "" )
  −
                    if not assigned.month then
  −
                        r1 = r1:gsub( "[ .%-]?[FmMnt][ .%-]*", "" )
   
                     end
 
                     end
 
                 end
 
                 end
             else
+
                return ret
                r1 = r1:gsub( " ?[yY] ?", "" )
+
             end -- fNum()
                if not assigned.dom then
+
        if self.bc then
                    r1 = r1:gsub( "[ .]?[dDjlNwz][ .,%-]*", "" )
+
            defs.year.max = 999999
                            :gsub( "^&#160;", "" )
+
        end
 +
        defs.dom.f =
 +
            function ()
 +
                local ret
 +
                local d
 +
                if access == "dom" then
 +
                    d = assign
 +
                else
 +
                    d = self.dom
 
                 end
 
                 end
            end
+
                if d then
            if template.lift and
+
                    ret = ( d <= 28 )
              (assigned.dom or
+
                    if not ret then
                not (assigned.month or assigned.year or assigned.bc)
+
                        local m
              ) then
+
                        if access == "month" then
                local stamp = false
+
                            m = assign
                if assigned.hour then
+
                        else
                    if assigned.min then
+
                            m = self.month
                         stamp = "H:i"
+
                         end
                         if assigned.sec then
+
                         if m then
                             stamp = "H:i:s"
+
                             ret = ( d <= Calc.months[ m ] )
                             if assigned.msec then
+
                             if ret then
                                 stamp = string.format( "%s.%d",
+
                                local y
                                                      stamp,
+
                                if access == "year" then
                                                      assigned.msec )
+
                                    y = assign
 +
                                 else
 +
                                    y = self.year
 +
                                end
 +
                                if d == 29  and  m == 2  and  y then
 +
                                    if y % 4 ~= 0  or
 +
                                      ( y % 100 == 0  and
 +
                                        y % 400 ~= 0 ) then
 +
                                        ret = false
 +
                                    end
 +
                                end
 
                             end
 
                             end
 
                         end
 
                         end
                    elseif adapt.lonely then
  −
                        stamp = "H"
   
                     end
 
                     end
 +
                else
 +
                    ret = true
 
                 end
 
                 end
                 if low or ask:find( "hh:mm:ss" ) then
+
                return ret
                     if stamp then
+
            end -- defs.dom.f()
                        r1 = string.format( "%s %s", r1, stamp )
+
        defs.sec.f =
                    end
+
            function ()
 +
                local ret
 +
                local second
 +
                 if access == "sec" then
 +
                     second = assign
 +
                else
 +
                    second = self.sec
 
                 end
 
                 end
                 if stamp then
+
                 if second then
                     if low or template.long then
+
                     ret = ( second <= 59 )
                        local scheme
+
                    if not ret and self.leap then
                        if template.long then
+
                         ret = true
                            scheme = mw.language.getContentLanguage()
  −
                            scheme = scheme.code
  −
                        end
  −
                         r2 = World.zones.formatter( assigned, scheme )
   
                     end
 
                     end
 
                 end
 
                 end
             end
+
                return ret
             if type ( assigned.bc ) == "boolean" then
+
             end -- defs.sec.f()
                 local eras = World.era[ adapt.lang ]  or  World.era.en
+
        if access or assign then
                 local i
+
             r = ( type( access ) == "string" )
                 if not r2 then
+
            if r then
                     r2 = ""
+
                 local def = defs[ access ]
 +
                if def then
 +
                    r = fNum( access, assign )
 +
                    if r then
 +
                        if def == "dom" or
 +
                          def == "month" or
 +
                          def == "year" then
 +
                            r = defs.dom.f()
 +
                        end
 +
                    end
 +
                 elseif access == "lang" then
 +
                    r = ( type( assign ) == "string" )
 +
                    if r then
 +
                        r = assign:match( "^%l%l%l?-?%a*$" )
 +
                    end
 +
                 elseif access == "london" then
 +
                     r = ( type( assign ) == "boolean" )
 
                 end
 
                 end
                 if assigned.bc then
+
            end
                     i = 1
+
        else
                 else
+
            local life  = false
                     i = 2
+
            local leak  = false
 +
            local s, v
 +
            for i = 1, 10 do
 +
                 s = Meta.order[ i ]
 +
                v = self[ s ]
 +
                if v then
 +
                    if not life and leak then
 +
                        -- gap detected
 +
                        r = false
 +
                        break
 +
                     else
 +
                        if not fNum( s, v ) then
 +
                            r = false
 +
                            break    -- for i
 +
                        end
 +
                        life = true
 +
                        leak = true
 +
                    end
 +
                 elseif i == 3 then
 +
                    if not self.week then
 +
                        life = false
 +
                     end
 +
                elseif i ~= 4 then
 +
                    life = false
 
                 end
 
                 end
                r2 = string.format( "%s&#160;%s", r2, eras[ i ] )
+
            end -- for i
 +
            if self.week  and  ( self.month or self.dom ) then
 +
                r = false
 
             end
 
             end
 
         end
 
         end
 
     end
 
     end
     return r1, r2
+
     return r
end -- World.templates.formatter()
+
end -- Prototypes.fair()
         −
World.zones.formatter = function ( assigned, align )
+
Prototypes.figure = function ( self, assign )
     -- Retrieve time zone specification string
+
     -- Assign month by name
 
     -- Parameter:
 
     -- Parameter:
     --    assigned  -- table, with numbers etc.
+
     --    self    -- table, to be filled
    --                  .zone should be available
+
     --    assign  -- string, with month name
     --    align    -- string, format spec, or nil
  −
    --                  nil, false, "+-"  -- +/- 0000
  −
    --                  "Z"              -- single letter
  −
    --                  "UTC"            -- "UTC", if appropriate
  −
    --                  "de"              -- try localized
   
     -- Returns:
 
     -- Returns:
     --    string
+
     --    number 1...12, if valid;  false, if not
     local r   = ""
+
     local r = false
     local move = 0
+
    if type( self ) == "table" and  type( assign ) == "string" then
     if assigned.zone then
+
        r = Parser.monthNumber( assign )
         local s = type( assigned.zone )
+
        if r then
         if s == "string" then
+
            self.month = r
             s = assigned.zone:upper()
+
        end
             if #s == 1 then
+
    end
                 -- "YXWVUTSRQPONZABCDEFGHIKLM"
+
    return r
                 move = World.zones[ "!" ]:find( s )
+
end -- Prototypes.figure()
                 if move then
+
 
                     move          = ( move - 13 ) * 100
+
 
                    assigned.zone = move
+
 
 +
Prototypes.first = function ( self )
 +
    -- Retrieve abbreviated month name in current language
 +
    -- Parameter:
 +
    --    self  -- table, to be evaluated
 +
    -- Returns:
 +
    --    string, if defined;  false, if not
 +
     local r
 +
     if type( self ) == "table"  and  self.month then
 +
         local slang = ( self.lang or World.slang )
 +
        r = World.monthsLong[ slang ]
 +
         if r then
 +
            local brief = World.monthsAbbr[ slang ]
 +
             r = r[ self.month ]
 +
             if brief then
 +
                 local ex = brief[ self.month ]
 +
                 local s  = brief.suffix
 +
                 if ex then
 +
                     r = ex[ 2 ]
 
                 else
 
                 else
                     assigned.zone = false
+
                     local n = brief.n or 3
 +
                    r = mw.ustring.sub( r, 1, n )
 
                 end
 
                 end
            else
+
                 if s then
                 local code = World.zones[ s ]
+
                    r = r .. s
                if not code then
  −
                  local slang = ( assigned.lang or
  −
                                  World.slang )
  −
                  local tmp  = World.zones[ slang ]
  −
                  if tmp then
  −
                      code = tmp[ s ]
  −
                  end
  −
                end
  −
                if code then
  −
                    move          = code
  −
                    assigned.zone = move
   
                 end
 
                 end
 
             end
 
             end
        elseif s == "number" then
  −
            move = assigned.zone
   
         end
 
         end
 +
    else
 +
        r = false
 
     end
 
     end
     if move then
+
     return r
         local spec = "+-"
+
end -- Prototypes.first()
         if align then
+
 
             if align == "Z" then
+
 
                 if move % 100 == 0 then
+
 
                     r = World.zones[ "!" ]:sub( move / 100 + 131 )
+
Prototypes.fix = function ( self )
                     spec = false
+
    -- Adapt this object to local time if no explicit zone given
 +
    -- Parameter:
 +
    --    self  -- table, with numbers etc.
 +
    if type( self ) == "table"  and
 +
      not self.zone then
 +
         local seconds = Prototypes.format( self, "Z" )
 +
        Prototypes.future( self,  - tonumber( seconds ) )
 +
    end
 +
end -- Prototypes.fix()
 +
 
 +
 
 +
 
 +
Prototypes.flow = function ( self, another, assert )
 +
    -- Compare this object with another timestamp
 +
    -- Parameter:
 +
    --    self    -- table, with numbers etc.
 +
    --    another  -- DateTime or string or nil (now)
 +
    --    assert  -- nil, or string with operator
 +
    --                      "lt", "le", "eq", "ne", "ge", "gt",
 +
    --                      "<", "<=", "==", "~=", "<>", ">=", "=>", ">"
 +
    -- Returns:
 +
    --    if assert: true or false
 +
    --    else: -1, 0, 1
 +
    --    nil if invalid
 +
    local base, other, r
 +
    if type( self ) == "table" then
 +
        base  = self
 +
        other = another
 +
    elseif type( another ) == "table" then
 +
        base  = another
 +
        other = self
 +
    end
 +
    if base then
 +
        if type( other ) ~= "table" then
 +
            other = Meta.fiat( other )
 +
        end
 +
         if type( other ) == "table" then
 +
            r = Private.flow( base, other )
 +
             if r  and  type( assert ) == "string" then
 +
                local trsl = { lt    = "<",
 +
                              ["<"]  = "<",
 +
                              le    = "<=",
 +
                              ["<="] = "<=",
 +
                              eq    = "=",
 +
                              ["=="] = "=",
 +
                              ne    = "<>",
 +
                              ["<>"] = "<>",
 +
                              ["~="] = "<>",
 +
                              ge    = ">=",
 +
                              [">="] = ">=",
 +
                              ["=>"] = ">=",
 +
                              gt    = ">",
 +
                              [">"]  = ">" }
 +
                local same = trsl[ assert:lower() ]
 +
                 if same then
 +
                    local s = "="
 +
                    if r < 0 then
 +
                        s = "<"
 +
                     elseif r > 0 then
 +
                        s = ">"
 +
                    end
 +
                    r = ( same:find( s, 1, true ) ~=  nil )
 +
                else
 +
                     r = nil
 
                 end
 
                 end
            elseif align ~= "+-" then
+
             end
                if move == 0 then
+
         end
                    r    = " UTC"
+
     end
                    spec = false
+
     return r
                else
+
end -- Prototypes.flow()
                    local part = World.zones[ align ]
  −
                    if part then
  −
                        for k, v in pairs( part ) do
  −
                            if v == move then
  −
                                r    = string.format( " (%s)", k )
  −
                                spec = false
  −
                                break
  −
                            end
  −
                        end -- for k, v
  −
                    end
  −
                end
  −
             end
  −
        end
  −
        if spec == "+-" then
  −
            if move < 0 then
  −
                spec = "%4.4d"
  −
            else
  −
                spec = "+%4.4d"
  −
            end
  −
            r = string.format( spec, move )
  −
            r = string.format( "%s:%s",
  −
                              r:sub( 1, 3), r:sub( 4 ) )
  −
         end
  −
     end
  −
     return r
  −
end -- World.zones.formatter()
           −
-- Export
+
Prototypes.format = function ( self, ask, adapt )
local p = { }
+
    -- Format object as string
 +
    -- Parameter:
 +
    --    self  -- table, with numbers etc.
 +
    --    ask    -- string, format spec, or nil
 +
    --              table, with multiple formats
 +
    --              string may contain multiple formats joined by "|||"
 +
    --    adapt  -- table, with options, or nil
 +
    --              .lang    -- string, with particular language code
 +
    --              .london  -- true: UTC output; default: local
 +
    --              .lonely  -- true: permit lonely hour
 +
    -- Returns:
 +
    --    string, or false, if invalid, or number for julian date
 +
    local r
 +
    if type( self ) == "table" then
 +
        local s = type( ask )
 +
        local poly
 +
        if s == "string"  and  ask:find( "|||", 1, true ) then
 +
            poly = mw.text.split( ask, "|||" )
 +
        elseif s == "table" then
 +
            poly = ask
 +
        end
 +
        if poly then
 +
            r = ""
 +
            for i = 1, #poly do
 +
                r = r .. Private.field( self, poly[ i ], adapt )
 +
            end -- for i
 +
        else
 +
            r = Private.field( self, ask, adapt )
 +
        end
 +
    end
 +
    return r  or  false
 +
end -- Prototypes.format()
 +
 
 +
 
   −
function p.test( args )
+
Prototypes.full = function ( self )
     local r
+
    -- Retrieve month name in current language
     local obj = DateTime( args[ 1 ], "de" )
+
    -- Parameter:
     if type( obj ) == "table" then
+
    --    self  -- table, to be evaluated
 +
    -- Returns:
 +
    --    string, if defined;  false, if not
 +
    local r
 +
    if type( self ) == "table"  and  self.month then
 +
        local slang = ( self.lang or World.slang )
 +
        r = World.monthsLong[ slang ]
 +
        if r then
 +
            r = r[ self.month ]
 +
        end
 +
    else
 +
        r = false
 +
    end
 +
    return r
 +
end -- Prototypes.full()
 +
 
 +
 
 +
 
 +
Prototypes.future = function ( self, add, allocate )
 +
    -- Relative move by interval
 +
    -- Parameter:
 +
    --    self      -- table, to be used as base
 +
    --    add      -- string or number, to be added
 +
    --    allocate  -- true, if a clone shall be returned
 +
    -- Returns:
 +
    --    table, with shift
 +
    local r, raw, rel, shift
 +
    if type( self ) == "table" then
 +
        r    = self
 +
        shift = add
 +
    elseif type( add ) == "table" then
 +
        r    = add
 +
        shift = self
 +
    end
 +
    if r then
 +
        if r[ Meta.signature ] then
 +
            raw = r[ Meta.signature ]
 +
        else
 +
            raw = r
 +
        end
 +
        if type( shift ) == "table" then
 +
            rel = shift
 +
        else
 +
            rel = Private.future( shift )
 +
        end
 +
    end
 +
    if raw and rel then
 +
        if allocate then
 +
            r  = Prototypes.clone( r )
 +
            raw = r[ Meta.signature ]
 +
        end
 +
        for k, v in pairs( rel ) do
 +
            raw[ k ] = ( raw[ k ] or 0 )  +  v
 +
        end -- for k, v
 +
        Calc.fair( raw )
 +
        r[ Meta.signature ] = raw
 +
    end
 +
    return r
 +
end -- Prototypes.future()
 +
 
 +
 
 +
 
 +
Prototypes.tostring = function ( self )
 +
    -- Stringify yourself
 +
    -- Parameter:
 +
    --    self  -- table, to be stringified
 +
    -- Returns:
 +
    --    string
 +
    local dels = { false, "", "-", "-", "", "", ":", ":", ".", "" }
 +
    local wids = { false, 4,  2,  2,  2,  2,  2,  2,  3,  3  }
 +
    local s    = ""
 +
    local n, r, spec
 +
    local f = function ( a )
 +
                  n = self[ Meta.order[ a ] ]
 +
                  s = s .. dels[ a ]
 +
                  if n then
 +
                      spec = string.format( "%%s%%0%dd", wids[ a ] )
 +
                      s    = string.format( spec, s, n )
 +
                  end
 +
              end -- f()
 +
    for i = 2, 5 do
 +
        f( i )
 +
    end -- for i
 +
    r = s
 +
    s = ""
 +
    for i = 6, 10 do
 +
        f( i )
 +
    end -- for i
 +
    if s == "::." then
 +
        r = r:gsub( "%-+$", "" )
 +
    else
 +
        if r == "--" then
 +
            r = s
 +
        else
 +
            r = string.format( "%sT%s", r, s )
 +
        end
 +
    end
 +
    r = r:gsub( "%.$", "" )
 +
    if self.bc then
 +
        if self.year then
 +
            r = "-" .. r
 +
        else
 +
            r = r .. " BC"
 +
        end
 +
    end
 +
    return r
 +
end -- Prototypes.tostring()
 +
 
 +
 
 +
 
 +
Prototypes.valueOf = function ( self )
 +
    -- Returns yourselves primitive value (primitive table)
 +
    -- Parameter:
 +
    --    self  -- table, to be dumped
 +
    -- Returns:
 +
    --    table, or false
 +
    local r
 +
    if type( self ) == "table" then
 +
        r = self[ Meta.signature ]
 +
    end
 +
    return r or false
 +
end -- Prototypes.valueOf()
 +
 
 +
 
 +
 
 +
Templates.flow = function ( frame, action )
 +
    -- Comparison invokation
 +
    -- Parameter:
 +
    --    frame  -- object
 +
    -- Returns:
 +
    --    string, either "" or "1"
 +
    local r
 +
    local s1 = frame.args[ 1 ]
 +
    local s2 = frame.args[ 2 ]
 +
    if s1 then
 +
        s1 = mw.text.trim( s1 )
 +
        if s1 == "" then
 +
            s1 = false
 +
        end
 +
    end
 +
    if s2 then
 +
        s2 = mw.text.trim( s2 )
 +
        if s2 == "" then
 +
            s2 = false
 +
        end
 +
    end
 +
    if s1 or s2 then
 +
        local l
 +
        Frame = frame
 +
        l, r = pcall( Prototypes.flow,
 +
                      Meta.fiat( s1 ), s2, action )
 +
        if r == true then
 +
            r = "1"
 +
        end
 +
    end
 +
    return r or ""
 +
end -- Templates.flow()
 +
 
 +
 
 +
 
 +
World.templates.formatter = function ( assigned, ask, adapt )
 +
    -- Retrieve format specification string
 +
    -- Parameter:
 +
    --    assigned  -- table, with numbers etc.
 +
    --    ask      -- string, format spec, or nil
 +
    --    adapt    -- table, with options
 +
    --                  .lang    -- string, with particular language code
 +
    --                  .lonely  -- true: permit lonely hour
 +
    -- Returns:
 +
    --    1  -- string
 +
    --    2  -- string or nil; append suffix (zone)
 +
    local r1, r2
 +
    if not ask  or  ask == "" then
 +
        r1 = "c"
 +
    elseif ask == "*" then
 +
        if World.present then
 +
            if assigned.hour then
 +
                if assigned.dom or assigned.month or assigned.year then
 +
                    if World.present.both and
 +
                      World.present.date and
 +
                      World.present.time then
 +
                        r1 = World.present.both
 +
                                    :gsub( "$date", World.present.date )
 +
                                    :gsub( "$time", World.present.time )
 +
                    else
 +
                        r1 = World.present.date
 +
                    end
 +
                end
 +
                r1 = r1 or World.present.time
 +
            else
 +
                r1 = World.present.date
 +
            end
 +
        end
 +
        r1 = r1 or "c"
 +
    else
 +
        local template = World.templates[ ask ]
 +
        r1 = ask
 +
        if not template then
 +
            local slang = ( adapt.lang or assigned.lang or World.slang )
 +
            local tmp  = World.templates[ slang ]
 +
            if tmp then
 +
                template = tmp[ ask ]
 +
            end
 +
            if not template then
 +
                local i = slang:find( "-", 3, true )
 +
                if i then
 +
                    slang = slang:sub( 1,  i - 1 ):lower()
 +
                    tmp  = World.templates[ slang ]
 +
                    if tmp then
 +
                        template = tmp[ ask ]
 +
                    end
 +
                end
 +
            end
 +
        end
 +
        if type( template ) == "table" then
 +
            local low = ( ask == "ISO" or ask == "ISO-T" )
 +
            r1 = template.spec
 +
            if assigned.year then
 +
                if not assigned.dom then
 +
                    r1 = r1:gsub( "[ .%-]?[dDjlNwz][ .,%-]*", "" )
 +
                          :gsub( "^&#160;", "" )
 +
                    if not assigned.month then
 +
                        r1 = r1:gsub( "[ .%-]?[FmMnt][ .%-]*", "" )
 +
                    end
 +
                end
 +
            else
 +
                r1 = r1:gsub( " ?[yY] ?", "" )
 +
                if not assigned.dom then
 +
                    r1 = r1:gsub( "[ .]?[dDjlNwz][ .,%-]*", "" )
 +
                            :gsub( "^&#160;", "" )
 +
                end
 +
            end
 +
            if template.lift and
 +
              ( assigned.dom or
 +
                not  ( assigned.month or assigned.year or assigned.bc )
 +
              ) then
 +
                local stamp = false
 +
                if assigned.hour then
 +
                    if assigned.min then
 +
                        stamp = "H:i"
 +
                        if assigned.sec then
 +
                            stamp = "H:i:s"
 +
                            if assigned.msec then
 +
                                stamp = string.format( "%s.%03d",
 +
                                                      stamp,
 +
                                                      assigned.msec )
 +
                                if assigned.mysec then
 +
                                    stamp = string.format( "%s.%03d",
 +
                                                          stamp,
 +
                                                        assigned.mysec )
 +
                                end
 +
                            end
 +
                        end
 +
                    elseif adapt.lonely then
 +
                        stamp = "H"
 +
                    end
 +
                end
 +
                if low or ask:find( "hh:mm:ss", 1, true ) then
 +
                    if stamp then
 +
                        r1 = string.format( "%s %s", r1, stamp )
 +
                    end
 +
                elseif ask:find( "hh:mm", 1, true )  and
 +
                      stamp  and
 +
                      #stamp > 3 then
 +
                    r1 = string.format( "%s H:i", r1 )
 +
                end
 +
                if stamp then
 +
                    if low or template.long then
 +
                        local scheme
 +
                        if template.long then
 +
                            scheme = mw.language.getContentLanguage()
 +
                            scheme = scheme.code
 +
                        end
 +
                        r2 = World.zones.formatter( assigned, scheme )
 +
                    end
 +
                end
 +
            end
 +
            if type ( assigned.bc ) == "boolean" then
 +
                local eras = World.era[ adapt.lang ]  or  World.era.en
 +
                local i
 +
                if not r2 then
 +
                    r2 = ""
 +
                end
 +
                if assigned.bc then
 +
                    i = 1
 +
                else
 +
                    i = 2
 +
                end
 +
                r2 = string.format( "%s&#160;%s", r2, eras[ i ] )
 +
            end
 +
        end
 +
    end
 +
    return r1, r2
 +
end -- World.templates.formatter()
 +
 
 +
 
 +
 
 +
World.zones.formatter =  function ( assigned, align )
 +
    -- Retrieve time zone specification string
 +
    -- Parameter:
 +
    --    assigned  -- table, with numbers etc.
 +
    --                  .zone should be available
 +
    --    align    -- string, format spec, or nil
 +
    --                  nil, false, "+-"  -- +/- 0000
 +
    --                  "Z"              -- single letter
 +
    --                  "UTC"            -- "UTC", if appropriate
 +
    --                  "de"              -- try localized
 +
    -- Returns:
 +
    --    string
 +
    local r    = ""
 +
    local move = 0
 +
    if assigned.zone then
 +
        local s = type( assigned.zone )
 +
        if s == "string" then
 +
            s = assigned.zone:upper()
 +
            if #s == 1 then
 +
                -- "YXWVUTSRQPONZABCDEFGHIKLM"
 +
                move = World.zones[ "!" ]:find( s, 1, true )
 +
                if move then
 +
                    move          = ( move - 13 ) * 100
 +
                    assigned.zone = move
 +
                else
 +
                    assigned.zone = false
 +
                end
 +
            else
 +
                local code = World.zones[ s ]
 +
                if not code then
 +
                  local slang = ( assigned.lang or
 +
                                  World.slang )
 +
                  local tmp  = World.zones[ slang ]
 +
                  if tmp then
 +
                      code = tmp[ s ]
 +
                  end
 +
                  if not code  and
 +
                      slang ~= "en"  and
 +
                      World.zones.en then
 +
                      code = World.zones.en[ s ]
 +
                  end
 +
                end
 +
                if code then
 +
                    move          = code
 +
                    assigned.zone = move
 +
                end
 +
            end
 +
        elseif s == "number" then
 +
            move = assigned.zone
 +
        end
 +
    end
 +
    if move then
 +
        local spec = "+-"
 +
        if align then
 +
            if align == "Z" then
 +
                if move % 100 == 0 then
 +
                    r = World.zones[ "!" ]:sub( move / 100 + 13,  1 )
 +
                    spec = false
 +
                end
 +
            elseif align ~= "+-" then
 +
                if move == 0 then
 +
                    r    = " UTC"
 +
                    spec = false
 +
                else
 +
                    local part = World.zones[ align ]
 +
                    if part then
 +
                        for k, v in pairs( part ) do
 +
                            if v == move then
 +
                                r    = string.format( " (%s)", k )
 +
                                spec = false
 +
                                break
 +
                            end
 +
                        end -- for k, v
 +
                    end
 +
                end
 +
            end
 +
        end
 +
        if spec == "+-" then
 +
            if move < 0 then
 +
                spec = "%4.4d"
 +
            else
 +
                spec = "+%4.4d"
 +
            end
 +
            r = string.format( spec, move )
 +
            r = string.format( "%s:%s",
 +
                              r:sub( 1, 3), r:sub( 4 ) )
 +
        end
 +
    end
 +
    return r
 +
end -- World.zones.formatter()
 +
 
 +
 
 +
 
 +
-- Export
 +
local p = { }
 +
 
 +
p.test = function ( args, alien )
 +
     local slang = args.lang or alien
 +
     local obj   = Meta.fiat( args[ 1 ], false, args.shift )
 +
    local r
 +
     if type( obj ) == "table" then
 +
        local spec  = args[ 2 ]
 
         local opt
 
         local opt
        local spec  = args[ 2 ]
+
         if spec then
        local slang = args[ 3 ]
+
             spec = mw.text.trim( spec )
         if spec then
+
         end
             spec = mw.text.trim( spec )
+
         if slang then
         end
+
             opt = { lang = mw.text.trim( slang ) }
         if slang then
+
         end
             opt = { lang = mw.text.trim( slang ) }
+
         r = obj:format( spec, opt )
         end
+
     else
         r = obj:format( spec, opt )
+
         r = ( args.noerror or "0" )
     else
+
         if r == "0" then
         r = ( args.noerror or "0" )
+
             r = fault( "Format invalid" )
         if r == "0" then
+
         else
             r = fault( "Format nicht erkannt" )
+
             r = ""
         else
+
        end
             r = ""
+
        if args.errCat then
         end
+
            local cats = mw.text.split( args.errCat, "%s*|%s*" )
     end
+
            for i = 1, #cats do
     return r
+
                r = string.format( "%s[[Category:%s]]",  r,  cats[ i ] )
end -- p.test
+
            end -- for i
 +
         end
 +
     end
 +
     return r
 +
end -- p.test
 +
 
 +
 
 +
 
 +
p.failsafe = function ( frame )
 +
    local s = type( frame )
 +
    local r, since
 +
    if s == "table" then
 +
        since = frame.args[ 1 ]
 +
    elseif s == "string" then
 +
        since = mw.text.trim( since )
 +
        if since == "" then
 +
            since = false
 +
        end
 +
    end
 +
    return Prototypes.failsafe( false, since )  or  ""
 +
end -- p.failsafe
 +
 
 +
 
 +
 
 +
p.format = function ( frame )
 +
    --    1      -- stamp
 +
    --    2      -- spec
 +
    --    lang
 +
    --    shift
 +
    --    noerror
 +
    local l, r
 +
    local v = { frame.args[ 1 ],
 +
                frame.args[ 2 ],
 +
                shift  = frame.args.shift,
 +
                noerror = frame.args.noerror,
 +
                errCat  = frame.args.errCat }
 +
    if not v[ 1 ]  or  v[ 1 ] == "now" then
 +
        v[ 1 ]  = frame:callParserFunction( "#timel", "c", v.shift )
 +
        v.shift = false
 +
    end
 +
    Frame  = frame
 +
    l, r = pcall( p.test,  v,  frame.args[ 3 ] or frame.args.lang )
 +
    if not l then
 +
        r = fault( r )
 +
    end
 +
    return r
 +
end -- p.format
         −
function p.format( frame )
+
p.lt = function ( frame )
     local l, r
+
     return Templates.flow( frame, "lt" )
    local v = { frame.args[ 1 ],
+
end -- p.lt
                frame.args[ 2 ],
+
p.le = function ( frame )
                frame.args[ 3 ],
+
    return Templates.flow( frame, "le" )
                noerror = frame.args.noerror }
+
end -- p.le
     if not v[ 1 ]  or  v[ 1 ] == "now" then
+
p.eq = function ( frame )
        v[ 1 ] = frame:callParserFunction( "#timel", "c" )
+
     return Templates.flow( frame, "eq" )
    end
+
end -- p.eq
    l, r = pcall( p.test, v )
+
p.ne = function ( frame )
    if not l then
+
    return Templates.flow( frame, "ne" )
        r = fault( r )
+
end -- p.ne
    end
+
p.ge = function ( frame )
     return r
+
    return Templates.flow( frame, "ge" )
end -- p.format
+
end -- p.ge
 +
p.gt = function ( frame )
 +
     return Templates.flow( frame, "gt" )
 +
end -- p.gt
         −
p.DateTime = function ( ... )
+
p.DateTime = function ()
     return DateTime( ... )
+
     return DateTime
 
end -- p.DateTime
 
end -- p.DateTime
    
return p
 
return p
Cookies helfen uns bei der Bereitstellung von imedwiki. Durch die Nutzung von imedwiki erklärst du dich damit einverstanden, dass wir Cookies speichern.

Navigationsmenü