gemeinsam neue Wege der Erkenntnis gehen
Eine freie Initiative von Menschen bei anthrowiki.at anthrowiki.at, anthro.world anthro.world, biodyn.wiki biodyn.wiki und steiner.wiki steiner.wiki
mit online Lesekreisen, Übungsgruppen, Vorträgen ...
Wie Sie die Entwicklung von AnthroWiki durch Ihre Spende unterstützen können, erfahren Sie hier.

Use Google Translate for a raw translation of our pages into more than 100 languages.
Please note that some mistranslations can occur due to machine translation.
Alle Banner auf einen Klick

Modul:Sort/cellDate

Aus AnthroWiki

Die Dokumentation für dieses Modul kann unter Modul:Sort/cellDate/Doku erstellt werden

local Sort = { suite   = "Sort",
               sub     = "cellDate",
               serial  = "2021-01-01",
               item    = 90149250,
               globals = { Cell     = 90144855,
                           DateTime = 20652535 } }
--[=[
Sort/cellDate -- support table cells with sortable date and time
]=]
local Failsafe  = Sort
local GlobalMod = Sort



Sort.mpz        = 0.7
Sort.maxYear    = 2099
Sort.minYear    = 100
Sort.similar    = mw.ustring.char( 8776 )    -- ~~
Sort.supreme    = mw.ustring.char( 8734 )    -- infinit
Sort.types      = { "date",
                    "time",
                    "isoDate",
                    "usLongDate" }
Sort.weights    = { }
Sort.weights.en = {
    [true]           = Sort.similar .. "abeus",
    ["before"]       = 3,
    ["begin"]        = 4,
    ["begin of"]     = 4,
    ["beginning"]    = 4,
    ["beginning of"] = 4,
    ["since"]        = 6,
    ["until"]        = 7,
    ["end of"]       = 8,
    ["after"]        = 9,
    ["about"]        = true,
    [Sort.similar]   = true
}



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 finer = function ()
                      if append then
                          storage = string.format( "%s/%s",
                                                   storage,
                                                   append )
                      end
                  end
    local fun, lucky, r, suited
    if advanced then
        fun = require
    else
        fun = mw.loadData
    end
    GlobalMod.globalModules = GlobalMod.globalModules or { }
    suited = GlobalMod.globalModules[ access ]
    if not suited then
        finer()
        lucky, r = pcall( fun,  "Module:" .. storage )
    end
    if not lucky then
        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
            finer()
            lucky, r = pcall( fun, storage )
        end
        if not lucky and alert then
            error( "Missing or invalid page: " .. storage )
        end
    end
    return r
end -- foreignModule()



local fetch = function ( access, append )
    -- Fetch global library
    -- Precondition:
    --     access    -- string|false, with name of base module
    --     append    -- string, with subpage part, if any; or false
    local store, sub, suite
    if access then
        suite = access
        store = access
    else
        suite = Sort.suite
        if append then
            sub   = append:lower()
            store = append
        else
            store = "Sorter"
        end
    end
    if type( Sort[ store ] ) == "nil" then
        local bib = foreignModule( suite,
                                   true,
                                   sub,
                                   Sort.globals[ store ],
                                   true )
        if bib  and  type( bib[ suite ] ) == "function" then
            Sort[ store ] = bib[ suite ]()
        else
            error( tostring( bib ) )
        end
    end
end -- fetch()



local fold = function ( access, alien, assign )
    -- Retrieve config table
    -- Precondition:
    --     access    -- string, external table
    --     alien     -- string, language code
    --     assign    -- string, local table
    -- Postcondition:
    --     Returns table, or not
    local r
    Sort[ assign ] = Sort[ assign ]  or  { }
    if type( Sort[ assign ][ alien ] ) == "nil" then
        local data = foreignModule( "DateTime", false, "local" )
        if data  and
           type( data[ access ] ) == "table" then
            Sort[ assign ][ alien ] = data[ access ][ alien ]
        else
            Sort[ assign ][ alien ] = false
        end
    end
    if type( Sort[ assign ][ alien ] ) == "table" then
        r = Sort[ assign ][ alien ]
    end
    return r
end -- fold()



local fore = function ( args )
    -- Create and merge sort attribute
    -- Precondition:
    --     args    -- table, parameters
    --                .d         -- table, with date
    --                .infinit   -- number|nil, out of ages, +/-1
    --                .pre       -- string|false, for prefix
    --                .type      -- string|false, for sorting
    -- Postcondition:
    --     attributes extended
    local d = { lang = args.d.lang }
    local latest, least, s, stamp
    if args.pre then
        local weights = fold( "sortWeights", d.lang, "weights" )
        local i
        if weights then
            i = weights[ args.pre ]
            if type( i ) == "number" then
                if i < 7 then
                   least = true
                else
                   latest = true
                end
            end
        end
    end
    if args.infinit then
        d.hour = 0
        if args.infinit > 0 then
            d.year  = Sort.maxYear
            d.month = 12
            d.dom   = 31
            d.min   = 59
            d.sec   = 59
        else
            d.month = 1
            d.dom   = 1
            d.min   = 0
            d.sec   = 0
            if args.type == "isoDate" then
                d.year = Sort.minYear
            elseif Sort.minYear < 0 then
                d.year = -1 * Sort.minYear
                d.bc   = true
            else
                d.year = Sort.minYear
            end
        end
        stamp = string.format( "%04d-%02d-%02d",
                               d.year, d.month, d.dom )
        if args.type == "isoDate" then
            stamp = string.format( "%sT%02d:%02d:%02d",
                                   stamp, d.hour, d.min, d.sec )
        end
    elseif args.type == "time" then
        if args.d.hour then
            d.hour = args.d.hour
        elseif least then
            d.hour = 0
        elseif latest then
            d.hour = 24
        else
            d.hour = 12
        end
        if args.d.min then
            d.min = args.d.min
        elseif least then
            d.min = 0
        elseif latest then
            d.min = 59
        else
            d.min = 30
        end
        if args.d.sec then
            d.sec = args.d.sec
        elseif least then
            d.sec = 0
        elseif latest then
            d.sec = 59
        else
            d.sec = 30
        end
        stamp = string.format( "%02d:%02d:%02d",
                               d.hour, d.min, d.sec )
    else
        args.d = Sort.DateTime( args.d )
        d.year = ( args.d.year or 0 )
        if args.d.bc  and  args.type == "isoDate" then
            d.bc = true
        else
            d.year = args.d.year or 0
        end
        if args.d.month then
            d.month = args.d.month
        elseif least then
            d.month = 1
        elseif latest then
            d.month = 12
        else
            d.month = 6
        end
        if args.d.dom then
            d.dom = args.d.dom
        elseif least then
            d.dom = 1
        else
            d.dom = tonumber( Sort.DateTime( d ):format( "t" ) )
            if not latest then
                d.dom = math.floor( 0.5 * d.dom )
            end
        end
        stamp = string.format( "%04d-%02d-%02d",
                               d.year, d.month, d.dom )
        if args.type == "isoDate"  and  args.d.hour then
            stamp = string.format( "%sT%02d",
                                   stamp, args.d.hour )
            if args.d.min then
                stamp = string.format( "%s:%02d",
                                       stamp, args.d.min )
                if args.d.sec then
                    stamp = string.format( "%s:%02d",
                                           stamp, args.d.sec )
                end
            end
        end
    end
    if args.type == "isoDate" then
        s = "c"
    elseif args.type == "time" then
        s = "H:i:s"
    elseif args.type == "usLongDate" then
        d.lang = "en"
        s = "F j, Y H:i:s"
    else
        s = "j M Y"
    end
    s = Sort.Cell.formatDate( s, stamp, true )
    if args.infinit then
        if args.infinit > 0 then
            s = s:gsub( tostring( Sort.maxYear ),  "9999" )
        elseif args.type == "isoDate" then
            s = s:gsub( string.format( "^%04d", Sort.minYear ),
                        "-999999" )
        end
    elseif args.type == "isoDate" and d.bc then
        s = "-" .. s
    end
    Sort.Cell.faced( args, s )
end -- fore()



local format = function ( args )
    -- Format visible date
    -- Precondition:
    --     args    -- table, parameters
    --                .d          -- table, with date
    --                .pattern    -- string, with format
    --                .target     -- string|nil, for formatting
    --                .url        -- string|nil, for formatting
    --                .pad        -- boolean, for padding
    --                .pre        -- string, for prefix
    --                .post       -- string, for postfix
    --                .type       -- string, for sorting
    -- Postcondition:
    --     Returns string
    local r, templates
    if not args.d.lang then
        args.d.lang = Sort.Cell.facility()
    end
    if args.pad  and  not args.pre then
        local scheme = args.pattern
        if scheme then
            local templates = fold( "templates",
                                    Sort.Cell.facility(),
                                    "templates" )
            if templates  and
               type( templates[ scheme ] ) == "table"  and
               type( templates[ scheme ].spec ) == "string" then
                scheme = templates[ scheme ].spec
            end
        end
        if scheme then
            local lift
            if args.type == "time" then
                lift = ( scheme:sub( 1, 1 ) == "G"  and
                         args.d.hour  and
                         args.d.hour < 10 )
            else
                lift = ( scheme:sub( 1, 1 ) == "j"  and
                         args.d.dom  and
                         args.d.dom < 10 )
            end
            if lift then
                if not Sort.shift then
                    if Sort.Cell.following() then
                        Sort.shift = "left"
                    else
                        Sort.shift = "right"
                    end
                    Sort.shift = "padding-" .. Sort.shift
                end
                Sort.Cell.feature( args,
                                   Sort.shift,
                                   string.format( "%.2fem !important",
                                                  Sort.mpz ) )
            end
        end
    end
    r = args.d:format( args.pattern or "*" )
    if type( args.target ) == "string" then
        if r == args.target then
            r = string.format( "[[%s]]", r )
        else
            r = string.format( "[[%s|%s]]", args.target, r )
        end
    elseif type( args.url ) == "string" then
        r = string.format( "[%s %s]", args.url, r )
    end
    if args.pre or args.post then
        local e
        if args.pre then
            r = string.format( "%s %s", args.pre, r )
        end
        if args.post then
            r = string.format( "%s %s", r, args.post )
        end
        e = mw.html.create( "span" )
                   :css( "white-space", "nowrap" )
                   :wikitext( r )
        r = tostring( e )
    end
    return r
end -- format()



local furnish = function ( args )
    -- Execute task
    -- Parameter:
    --     args    -- table, parameters
    -- Postcondition:
    --     Returns string, or expands .cell
    --     Throws error on failure
    local r
    fetch( false, "Cell" )
    fetch( "DateTime" )
    if type( args ) == "table" then
        local present = Sort.Cell.first( args, true )
        local s
        Sort.Cell.fair( args, "d", present )
        if not present.lang then
            present.lang = Sort.Cell.facility()
        end
        if type( present.d ) == "string"  and
           mw.ustring.find( present.d, Sort.supreme, 1, true ) then
            s = mw.text.trim( present.d )
            if s == Sort.supreme then
                present.infinit = 1
            elseif mw.ustring.len( s ) == 2  and
                   mw.ustring.codepoint( s, 2, 2 ) == 8734 then
                local m = mw.ustring.codepoint( s, 1, 1 )
                if m == 45  or  m == 8722 then
                    present.infinit = -1
                elseif m == 43 then
                    present.infinit = 1
                end
            end
        end
        if present.infinit then
            present.d = { lang = Sort.Cell.facility() }
        else
            Sort.Cell.fair( args, "pre", present )
            s = type( present.d )
            if s == "string"  and  not present.pre then
                local weights = fold( "sortWeights",
                                      present.lang,
                                      "weights" )
                if weights  and  weights[ true ] then
                    local sw = weights[ true ]
                    if type( sw ) == "string" then
                        local slim
                        slim = mw.ustring.sub( present.d, 1, 1 )
                        slim = mw.ustring.lower( slim )
                        if mw.ustring.find( sw, slim, 1, true ) then
                            local n
                            for k, v in pairs( weights ) do
                                if type( k ) == "string" then
                                    n    = mw.ustring.len( k )
                                    slim = mw.ustring.sub( present.d,
                                                           1,
                                                           n )
                                    if slim == k then
                                        present.pre = k
                                        present.d   = mw.text.trim(
                                               mw.ustring.sub( present.d,
                                                               n + 1 ) )
                                        break -- for k, v
                                    end
                                end
                            end -- for k, v
                        end
                    end
                end
            end
            if s == "string" then
                if present.d == "" then
                    s = "now"
                else
                    s = present.d
                end
                present.d = Sort.DateTime( s, args.lang )
            elseif s ~= "table" then
                present.d = Sort.DateTime( "now", args.lang )
            end
        end
        if type( present.d ) == "table" then
            if present.d.hour then
                local memory = present.d.sec
                present.d:fix()
                if not memory then
                    present.d.sec = nil
                end
            end
            Sort.Cell.fair( args, "type", present )
            if type( present.type ) == "string" then
                local n
                s = present.type
                n = #s
                if n > 0 then
                    local sort
                    s = s:lower()
                    for i = 1, #Sort.types do
                        sort = Sort.types[ i ]:sub( 1, n ):lower()
                        if s == sort then
                            present.type = Sort.types[ i ]
                            break    -- for i
                        end
                    end -- i = 1, #Sort.types
                end
            end
            if not present.infinit then
                Sort.Cell.fair( args, "pattern", present )
                if present.pattern ~= "-" then
                    if present.pattern then
                        present.pattern =
                           present.pattern:gsub( "\\ ",    " " )
                                          :gsub( "&nbsp;", "&#160;" )
                    end
                    Sort.Cell.fair( args, "target", present )
                    Sort.Cell.fair( args, "url", present )
                    s = type( args.pad )
                    if s == "string" then
                        present.pad = ( args.pad == "1" )
                    elseif s == "boolean" then
                        present.pad = args.pad
                    end
                    Sort.Cell.fair( args, "post", present )
                    r = format( present )
                end
            end
            fore( present )
            r = Sort.Cell.finalize( present, r )
        else
            r = Sort.Cell.fault( "?!?!?!", args )
        end
    else
        error( "'args' is not a table" )
    end
    return r
end -- furnish()



Sort.f = function ( args )
    -- Create table cell start
    -- Parameter:
    --     args    -- table, parameters
    --                .d          -- string|table, with date
    --                .pattern    -- string, with format
    --                .lang       -- string, for formatting
    --                .target     -- string|nil, for formatting
    --                .url        -- strin|nil, for formatting
    --                .pad        -- boolean, for padding
    --                .pre        -- string, for prefix
    --                .post       -- string, for postfix
    --                .cell       -- table|nil, sort environment
    --                .type       -- string, for sorting mode
    --                .rowspan    -- number|string, for cell attribute
    --                .colspan    -- number|string, for cell attribute
    --                .class      -- string, for cell attribute
    --                .style      -- string|table, for cell attribute
    --                .id         -- string, for cell attribute
    --                .dir        -- string, for cell attribute
    --                .cat        -- string|nil, for error category
    -- Postcondition:
    --     Returns string, or expands .cell
    local lucky, r = pcall( furnish, args )
    if not lucky then
        local e = mw.html.create( "span" )
                         :addClass( "error" )
                         :wikitext( "Module:Sort/cell * " .. r )
        if type( args.cell ) == "table"  and
           type( args.cell.wikitext ) == "function" then
            args.cell:node( e )
        else
            r = tostring( e )
        end
    end
    return r
end -- Sort.f()



Sort.furnish = function ()
    -- Retrieve list of project prefixes
    -- Postcondition:
    --     Returns  string  -- with wikitext list
    --              false   -- if none
    local r, weights
    fetch( false, "Cell" )
    weights = fold( "sortWeights", Sort.Cell.facility(), "weights" )
    if weights  and  weights[ true ] then
        local order = { }
        for k, v in pairs( weights ) do
            if type( k ) == "string" then
                table.insert( order, k )
            end
        end -- for k, v
        table.sort( order )
        for i = 1, #order do
            if r then
                r = r .. "\n"
            else
                r = ""
            end
            r = string.format( "%s* %s", r, order[ i ] )
        end -- i = 1, #order
    end
    return r
end -- Sort.furnish()



Failsafe.failsafe = function ( atleast )
    -- Retrieve versioning and check for compliance
    -- Precondition:
    --     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-01
    local last  = ( atleast == "~" )
    local link  = ( atleast == "@" )
    local since = atleast
    local r
    if last  or  link  or  since == "wikidata" then
        local item = Failsafe.item
        since = false
        if type( item ) == "number"  and  item > 0 then
            local suited = string.format( "Q%d", item )
            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 == Failsafe.serial then
                        r = false
                    elseif link then
                        if mw.title.getCurrentTitle().prefixedText  ==
                           mw.wikibase.getSitelink( suited ) then
                            r = false
                        else
                            r = suited
                        end
                    else
                        r = vsn.value
                    end
                end
            end
        end
    end
    if type( r ) == "nil" then
        if not since  or  since <= Failsafe.serial then
            r = Failsafe.serial
        else
            r = false
        end
    end
    return r
end -- Failsafe.failsafe()



-- Export
local p = { }

p.f = function ( frame )
    -- Template call
    Sort.frame = frame
    return Sort.f( frame.args )  or  ""
end -- p.f

p.failsafe = function ( frame )
    -- Versioning interface
    local s = type( frame )
    local since
    if s == "table" then
        since = frame.args[ 1 ]
    elseif s == "string" then
        since = frame
    end
    if since then
        since = mw.text.trim( since )
        if since == "" then
            since = false
        end
    end
    return Failsafe.failsafe( since )  or  ""
end -- p.failsafe

p.furnish = function ()
    return Sort.furnish()  or  ""
end -- p.f

p.Sort = function ()
    -- Module interface
    return Sort
end

return p