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( " ", " " ) 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