|
|
| Zeile 1: |
Zeile 1: |
| − | local DateTime = { serial = "2017-04-29",
| |
| − | suite = "DateTime" } -- Date and time objects
| |
| − | local Calc = { }
| |
| − | local Meta = { }
| |
| − | local Parser = { }
| |
| − | local Private = { }
| |
| − | local Prototypes = { }
| |
| − | local Templates = { }
| |
| − | local World = { slang = "en",
| |
| − | monthsLong = { },
| |
| − | monthsParse = { },
| |
| − | months4 = { } }
| |
| − | local MaxYear = 2099
| |
| − | local Nbsp = mw.ustring.char( 160 )
| |
| − | local Tab = mw.ustring.char( 9 )
| |
| − | local Frame
| |
| − | World.era = { en = { "BC", "AD" } }
| |
| − | World.monthsAbbr = { en = { n = 3 } }
| |
| − | World.monthsLong.en = { "January",
| |
| − | "February",
| |
| − | "March",
| |
| − | "April",
| |
| − | "May",
| |
| − | "June",
| |
| − | "July",
| |
| − | "August",
| |
| − | "September",
| |
| − | "October",
| |
| − | "November",
| |
| − | "December"
| |
| − | }
| |
| − | World.monthsParse.en = { [ "Apr" ] = 4,
| |
| − | [ "Aug" ] = 8,
| |
| − | [ "Dec" ] = 12,
| |
| − | [ "Feb" ] = 2,
| |
| − | [ "Jan" ] = 1,
| |
| − | [ "Jul" ] = 7,
| |
| − | [ "Jun" ] = 6,
| |
| − | [ "Mar" ] = 3,
| |
| − | [ "May" ] = 5,
| |
| − | [ "Nov" ] = 11,
| |
| − | [ "Oct" ] = 10,
| |
| − | [ "Sep" ] = 9
| |
| − | }
| |
| − | World.months4.en = { [ 6 ] = true,
| |
| − | [ 7 ] = true }
| |
| − | World.templates = { [ "ISO" ] =
| |
| − | { spec = "Y-m-d",
| |
| − | lift = true },
| |
| − | [ "ISO-T" ] =
| |
| − | { spec = "c" },
| |
| − | [ "timestamp" ] =
| |
| − | { spec = "YmdHis" },
| |
| − | [ "default" ] =
| |
| − | { spec = "H:i, j M Y",
| |
| − | long = true },
| |
| − | [ "$dmy" ] =
| |
| − | { spec = "H:i, j M Y",
| |
| − | long = true },
| |
| − | [ "$ymd" ] =
| |
| − | { spec = "H:i, Y M j",
| |
| − | long = true },
| |
| − | [ "$dmyt" ] =
| |
| − | { spec = "j M Y, H:i",
| |
| − | long = true },
| |
| − | [ "$dmyts" ] =
| |
| − | { spec = "j M Y, H:i:s",
| |
| − | long = true },
| |
| − | [ "data-sort-type:date" ] =
| |
| − | { spec = "j M Y" }
| |
| − | }
| |
| − | World.templates.en = { }
| |
| − | World.zones = {
| |
| − | [ "!" ] = "YXWVUTSRQPONZABCDEFGHIKLM",
| |
| − | UTC = 0,
| |
| − | GMT = 0 -- Greenwich Mean Time
| |
| − | }
| |
| − | World.zones.en = {
| |
| − | BST = 100, -- British Summer Time
| |
| − | IST = 100, -- Irish Summer Time
| |
| − | WET = 0, -- Western Europe Time
| |
| − | WEST = 100, -- Western Europe Summer Time
| |
| − | CET = 100, -- Central Europe Time
| |
| − | CEST = 200, -- Central Europe Summer Time
| |
| − | EET = 200, -- Eastern Europe Time
| |
| − | EEST = 300, -- Eastern Europe Summer Time
| |
| − | MSK = 300, -- Moscow Time
| |
| − | MSD = 400, -- Moscow Summer Time
| |
| − | NST = -330, -- Newfoundland Standard Time
| |
| − | NDT = -230, -- Newfoundland Daylight Time
| |
| − | AST = -400, -- Atlantic Standard Time
| |
| − | ADT = -300, -- Atlantic Daylight Time
| |
| − | EST = -500, -- Eastern Standard Time
| |
| − | EDT = -400, -- Eastern Daylight Saving Time
| |
| − | CST = -600, -- Central Standard Time
| |
| − | CDT = -500, -- Central Daylight Saving Time
| |
| − | MST = -700, -- Mountain Standard Time
| |
| − | MDT = -600, -- Mountain Daylight Saving Time
| |
| − | PST = -800, -- Pacific Standard Time
| |
| − | PDT = -700, -- Pacific Daylight Saving Time
| |
| − | AKST = -900, -- Alaska Standard Time
| |
| − | AKDT = -800, -- Alaska Standard Daylight Saving Time
| |
| − | HST = -1000 -- Hawaiian Standard Time
| |
| − | }
| |
| | | | |
| − |
| |
| − |
| |
| − | local function capitalize( a )
| |
| − | -- Upcase first character, downcase anything else
| |
| − | -- Parameter:
| |
| − | -- a -- string
| |
| − | -- Returns:
| |
| − | -- string
| |
| − | return mw.ustring.upper( mw.ustring.sub( a, 1, 1 ) )
| |
| − | .. mw.ustring.lower( mw.ustring.sub( a, 2 ) )
| |
| − | end -- capitalize()
| |
| − |
| |
| − |
| |
| − |
| |
| − | local function fault( a )
| |
| − | -- Format error message by class=error
| |
| − | -- Parameter:
| |
| − | -- a -- string, error message
| |
| − | -- Returns:
| |
| − | -- string, HTML span
| |
| − | return string.format( "<span class=\"error\">%s</span>", a )
| |
| − | end -- fault()
| |
| − |
| |
| − |
| |
| − |
| |
| − | local function frame()
| |
| − | 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:
| |
| − | -- assign -- string, with initial timestamp, or nil
| |
| − | -- nil -- now
| |
| − | -- false -- empty object
| |
| − | -- table -- clone this object, or copy from raw
| |
| − | -- ignore remaining parameters
| |
| − | -- alien -- string, with language code, or nil
| |
| − | -- add -- string, with interval (PHP strtotime), or nil
| |
| − | -- Returns:
| |
| − | -- table, as DateTime object
| |
| − | -- string or false, if failed
| |
| − | local r
| |
| − | Private.foreign()
| |
| − | 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
| |
| − | r = { [ Meta.signature ] = r }
| |
| − | setmetatable( r, Meta.tableI )
| |
| − | end
| |
| − | return r
| |
| − | end -- Meta.fiat()
| |
| − | setmetatable( DateTime, Meta.tableL )
| |
| − | DateTime.serial = nil
| |
| − |
| |
| − |
| |
| − |
| |
| − | Calc.months = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
| |
| − |
| |
| − |
| |
| − |
| |
| − | -- 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 n > 1 and
| |
| − | adjust.month >= 1 and
| |
| − | adjust.month <= 12 and
| |
| − | adjust.year > 1900 then
| |
| − | max = Calc.months[ adjust.month ]
| |
| − | if adjust.month == 2 and
| |
| − | ( adjust.year % 4 ~= 0 or
| |
| − | adjust.year % 400 == 0 ) then
| |
| − | max = 28
| |
| − | end
| |
| − | if n <= max then
| |
| − | max = false
| |
| − | end
| |
| − | end
| |
| − | if max then
| |
| − | m = n % 30
| |
| − | move = ( n - m ) / 30
| |
| − | n = 1 + m
| |
| − | end
| |
| − | end
| |
| − |
| |
| − | end
| |
| − | adjust[ s ] = n
| |
| − | end
| |
| − | end
| |
| − | end -- for i
| |
| − | end -- Calc.fair()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Calc.future = function ( add )
| |
| − | -- Parse move interval
| |
| − | -- 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
| |
| − | break -- while true
| |
| − | end
| |
| − | end -- while true
| |
| − | 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 n == 14 then
| |
| − | -- timestamp
| |
| − | 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 ) )
| |
| − | r.min = tonumber( analyse:sub( 11, 2 ) )
| |
| − | r.sec = tonumber( analyse:sub( 13, 2 ) )
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | elseif amount == 4 then
| |
| − | local s, sep, sx = analyse:match( "^(%d+)([%-%.:Ww]?)(.*)$" )
| |
| − | r.year = tonumber( s )
| |
| − | if sep == "-" then
| |
| − | -- ISO
| |
| − | s, sep, sx = sx:match( "^(%d%d)(-?)(.*)$" )
| |
| − | if s then
| |
| − | r.month = tonumber( s )
| |
| − | r.month2 = true
| |
| − | if sep == "-" then
| |
| − | s, sep, sx = sx:match( "^(%d%d?)([ T]?)(.*)$" )
| |
| − | if s then
| |
| − | r.dom = tonumber( s )
| |
| − | if sep == "T" then
| |
| − | r.month2 = nil
| |
| − | else
| |
| − | r.dom2 = ( #s == 2 )
| |
| − | end
| |
| − | if sep then
| |
| − | r = Parser.time( sx, r, sep == "T" )
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | elseif sx and sx ~= "" then
| |
| − | r = false
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | elseif sep:lower() == "w" then
| |
| − | if sx then
| |
| − | s = sx:match( "^(%d%d?)$" )
| |
| − | if s then
| |
| − | r.week = tonumber( s )
| |
| − | if r.week < 1 or r.week > 53 then
| |
| − | r = false
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | if r then
| |
| − | r.iso = true
| |
| − | end
| |
| − | elseif amount == 8 then
| |
| − | -- ISO compact
| |
| − | local s, sz = analyse:match( "^%d+T(%d+)([.+-]?%d*%a*)$" )
| |
| − | if s then
| |
| − | local n = #s
| |
| − | if n == 2 or n == 4 or n == 6 then
| |
| − | 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( 10, 11 ) )
| |
| − | if n > 2 then
| |
| − | r.min = tonumber( s:sub( 3, 4 ) )
| |
| − | if n == 6 then
| |
| − | r.sec = tonumber( s:sub( 5, 6 ) )
| |
| − | end
| |
| − | n, s = sz:match( "^(%.%d+)([+-]?[%a%d]*)$" )
| |
| − | if n then
| |
| − | n = n .. "00"
| |
| − | r.msec = tonumber( n:sub( 1, 3 ) )
| |
| − | if #n >= 6 then
| |
| − | r.mysec = tonumber( n:sub( 4, 6 ) )
| |
| − | end
| |
| − | sz = s
| |
| − | end
| |
| − | end
| |
| − | if sz ~= "" then
| |
| − | s, sz = sz:match( "^([+-]?)(%a*)$" )
| |
| − | if s == "" then
| |
| − | if sz:match( "^(%u)$" ) then
| |
| − | r.zone = sz
| |
| − | else
| |
| − | s = false
| |
| − | end
| |
| − | elseif #s == 1 then
| |
| − | r.zone = s .. sz
| |
| − | else
| |
| − | s = false
| |
| − | end
| |
| − | end
| |
| − | else
| |
| − | s = false
| |
| − | end
| |
| − | end
| |
| − | if s then
| |
| − | r = false
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- Parser.digitsHeading()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.eraGermanEnglish = function ( analyse )
| |
| − | -- String analysis, for German and English era
| |
| − | -- v. Chr. v. u. Z. n. Chr. AD BC A.D. B.C. B.C.E.
| |
| − | -- Parameter:
| |
| − | -- analyse -- string
| |
| − | -- Returns:
| |
| − | -- 1 -- table, with boolean era, if any
| |
| − | -- 2 -- string, with era stripped off, if any
| |
| − | local rO = { }
| |
| − | local rS = analyse
| |
| − | local s, switch = analyse:match( "^(.+) ([vn])%. ?Chr%.$" )
| |
| − | if switch then
| |
| − | rS = s
| |
| − | rO.bc = ( switch == "v" )
| |
| − | elseif analyse:find( " v%. ?u%. ?Z%.$" ) then
| |
| − | rS = analyse:match( "^(.+) v%. ?u%. ?Z%.$" )
| |
| − | rO.bc = true
| |
| − | elseif analyse:find( " B%.? ?C%.? ?E?%.?$" ) then
| |
| − | rS = analyse:match( "^(.+) B%.? ?C%.? ?E?%.?$" )
| |
| − | rO.bc = true
| |
| − | elseif analyse:find( "^A%.? ?D%.? " ) then
| |
| − | rS = analyse:match( "^A%.? ?D%.? (.*)$" )
| |
| − | rO.bc = false
| |
| − | end
| |
| − | return rO, rS
| |
| − | end -- Parser.eraGermanEnglish()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.european = function ( ahead, adhere, analyse, assign )
| |
| − | -- String analysis, retrieve date style: DOM MONTH YEAR
| |
| − | -- Parameter:
| |
| − | -- ahead -- string, with first digits, not more than 2
| |
| − | -- adhere -- string, with first separator; not ":"
| |
| − | -- analyse -- string, remainder following adhere
| |
| − | -- assign -- table
| |
| − | -- Returns:
| |
| − | -- table, extended if parsed
| |
| − | local r = assign
| |
| − | local s, s2, sx
| |
| − | if adhere == "." or adhere == ". " then
| |
| − | -- 23.12.2013
| |
| − | -- 23. Dezember 2013
| |
| − | s, sx = analyse:match( "^(%d%d?)%.(.*)$" )
| |
| − | if s then
| |
| − | r = Parser.putDate( false, s, ahead, assign )
| |
| − | r = Parser.yearTime( sx, r )
| |
| − | else
| |
| − | s, sx = mw.ustring.match( analyse,
| |
| − | "^ ?([%a&;]+%.?) ?(.*)$" )
| |
| − | if s then
| |
| − | local n = Parser.monthNumber( s )
| |
| − | if n then
| |
| − | r.month = n
| |
| − | r.dom = tonumber( ahead )
| |
| − | r.dom2 = ( #ahead == 2 )
| |
| − | r = Parser.yearTime( sx, r )
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | end
| |
| − | elseif adhere == " " then
| |
| − | -- 23 Dec 2013
| |
| − | s, sx = mw.ustring.match( analyse,
| |
| − | "^([%a&;]+%.?) ?(.*)$" )
| |
| − | if s then
| |
| − | local n = Parser.monthNumber( s )
| |
| − | if n then
| |
| − | r.month = n
| |
| − | r.dom = tonumber( ahead )
| |
| − | r.dom2 = ( #ahead == 2 )
| |
| − | r = Parser.yearTime( sx, r )
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | return r
| |
| − | end -- Parser.european()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.isoDate = function ( analyse, assign )
| |
| − | -- String analysis, retrieve month heading ISO date
| |
| − | -- Parameter:
| |
| − | -- analyse -- string, with heading hyphen
| |
| − | -- assign -- table
| |
| − | -- Returns:
| |
| − | -- 1 -- table, extended if parsed
| |
| − | -- 2 -- stripped string, or false, if invalid text format
| |
| − | local rO, rS
| |
| − | if analyse:match( "^%-%-?[0-9]" ) then
| |
| − | local n, s
| |
| − | rO = assign
| |
| − | rS = analyse:sub( 2 )
| |
| − | s = rS:match( "^([012][0-9])%-" )
| |
| − | if s then
| |
| − | n = tonumber( s )
| |
| − | if n >= 1 and n <= 12 then
| |
| − | rO.month = n
| |
| − | rS = rS:sub( 3 )
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | end
| |
| − | if rO then
| |
| − | if rS:byte( 1, 1 ) == 45 then
| |
| − | local suffix
| |
| − | s = rS:match( "^%-([012][0-9])" )
| |
| − | if s then
| |
| − | n = tonumber( s )
| |
| − | if n >= 1 and n <= 31 then
| |
| − | rO.dom = n
| |
| − | rS = rS:sub( 4 )
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | else
| |
| − | rS:sub( 2 )
| |
| − | end
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | if rO then
| |
| − | if #rS > 0 then
| |
| − | if rO.dom then
| |
| − | n = rS:byte( 1, 1 )
| |
| − | if n == 32 or n == 84 then
| |
| − | rS = rS:sub( 2 )
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | if rO then
| |
| − | rO.iso = true
| |
| − | else
| |
| − | rS = false
| |
| − | end
| |
| − | return rO, rS
| |
| − | end -- Parser.isoDate()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.monthHeading = function ( analyse, assign )
| |
| − | -- String analysis, retrieve month heading date (US only)
| |
| − | -- Parameter:
| |
| − | -- analyse -- string, with heading word
| |
| − | -- assign -- table
| |
| − | -- Returns:
| |
| − | -- 1 -- table, extended if parsed
| |
| − | -- 2 -- stripped string, or false, if invalid text format
| |
| − | local rO = assign
| |
| − | local rS = analyse
| |
| − | local s, sep = mw.ustring.match( analyse, "^([%a&;]+%.?)([^%a%.]?)" )
| |
| − | if s then
| |
| − | -- might begin with month name "December 23, 2013"
| |
| − | local n = Parser.monthNumber( s )
| |
| − | if n then
| |
| − | rO.month = n
| |
| − | if sep == "" then
| |
| − | rS = ""
| |
| − | else
| |
| − | local s2, s3
| |
| − | n = mw.ustring.len( s ) + 1
| |
| − | s = mw.ustring.sub( analyse, n )
| |
| − | s2 = s:match( "^ (%d%d%d?%d?)$" )
| |
| − | if s2 then
| |
| − | rO.year = tonumber( s2 )
| |
| − | rS = ""
| |
| − | else
| |
| − | s2, s3, rS = s:match( "^ (%d+), (%d+)( ?.*)$" )
| |
| − | if s2 and s3 then
| |
| − | n = #s2
| |
| − | if n <= 2 and #s3 == 4 then
| |
| − | rO.dom = tonumber( n )
| |
| − | rO.year = tonumber( s3 )
| |
| − | rO.dom2 = ( n == 2 )
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | if not rO then
| |
| − | rS = false
| |
| − | end
| |
| − | return rO, rS
| |
| − | end -- Parser.monthHeading()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.monthNumber = function ( analyse )
| |
| − | -- String analysis, retrieve month number
| |
| − | -- Parameter:
| |
| − | -- analyse -- string, with month name including any period
| |
| − | -- Returns:
| |
| − | -- number, 1...12 if found
| |
| − | -- false or nil, if not detected
| |
| − | local r = false
| |
| − | local s = mw.ustring.match( analyse, "^([%a&;]+)%.?$" )
| |
| − | if s then
| |
| − | local given
| |
| − | s = capitalize( s )
| |
| − | for k, v in pairs( World.monthsLong ) do
| |
| − | given = World.monthsParse[ k ]
| |
| − | if given then
| |
| − | r = given[ s ]
| |
| − | end
| |
| − | if not r then
| |
| − | given = World.monthsLong[ k ]
| |
| − | for i = 1, 12 do
| |
| − | if given[ i ] == s then
| |
| − | r = i
| |
| − | break
| |
| − | end
| |
| − | end -- for i
| |
| − | end
| |
| − | if r then
| |
| − | break
| |
| − | end
| |
| − | end -- for k, v
| |
| − | end
| |
| − | return r
| |
| − | end -- Parser.monthNumber()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.putDate = function ( aYear, aMonth, aDom, assign )
| |
| − | -- Store date strings
| |
| − | -- Parameter:
| |
| − | -- aYear -- string, with year, or false
| |
| − | -- aMonth -- string, with numeric month
| |
| − | -- aDom -- string, with day of month
| |
| − | -- assign -- table
| |
| − | -- Returns:
| |
| − | -- table, extended
| |
| − | local r = assign
| |
| − | if aYear then
| |
| − | r.year = tonumber( aYear )
| |
| − | end
| |
| − | r.month = tonumber( aMonth )
| |
| − | r.dom = tonumber( aDom )
| |
| − | r.month2 = ( #aMonth == 2 )
| |
| − | r.dom2 = ( #aDom == 2 )
| |
| − | return r
| |
| − | end -- Parser.putDate()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.time = function ( analyse, assign, adjusted )
| |
| − | -- String analysis, retrieve time components
| |
| − | -- Parameter:
| |
| − | -- analyse -- string, with time part
| |
| − | -- assign -- table
| |
| − | -- adjusted -- true: fixed length of 2 digits expected
| |
| − | -- Returns:
| |
| − | -- table, extended if parsed
| |
| − | -- false, if invalid text format
| |
| − | local r = assign
| |
| − | if analyse ~= "" then
| |
| − | local s, sx = analyse:match( "^(%d+)(:?.*)$" )
| |
| − | if s then
| |
| − | local n = #s
| |
| − | if n <= 2 then
| |
| − | r.hour = tonumber( s )
| |
| − | if not adjusted then
| |
| − | r.hour2 = ( n == 2 )
| |
| − | end
| |
| − | else
| |
| − | sx = false
| |
| − | r = false
| |
| − | end
| |
| − | if sx then
| |
| − | s, sx = sx:match( "^:(%d+)(:?(.*))$" )
| |
| − | if s then
| |
| − | if #s == 2 then
| |
| − | r.min = tonumber( s )
| |
| − | if sx == "" then
| |
| − | sx = false
| |
| − | end
| |
| − | else
| |
| − | sx = false
| |
| − | r = false
| |
| − | end
| |
| − | if sx then
| |
| − | local sep
| |
| − | local scan = "^([:,] ?)(%d+)(.*)$"
| |
| − | sep, s, sx = sx:match( scan )
| |
| − | if sep == ":" then
| |
| − | if #s == 2 then
| |
| − | r.sec = tonumber( s )
| |
| − | end
| |
| − | elseif sep == ", " then
| |
| − | r = Parser.wikiDate( s .. sx, r )
| |
| − | sx = false
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | end
| |
| − | if sx and sx ~= "" then
| |
| − | s = sx:match( "^%.(%d+)$" )
| |
| − | if s then
| |
| − | s = s .. "00"
| |
| − | r.msec = tonumber( s:sub( 1, 3 ) )
| |
| − | if #s >= 6 then
| |
| − | r.mysec = tonumber( s:sub( 4, 6 ) )
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- Parser.time()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.wikiDate = function ( analyse, assign )
| |
| − | -- String analysis, for date after wiki ~~~~~ signature time
| |
| − | -- dmy 10:28, 30. Dez. 2013
| |
| − | -- ymd 10:28, 2013 Dez. 30
| |
| − | -- Parameter:
| |
| − | -- analyse -- string
| |
| − | -- assign -- table
| |
| − | -- Returns:
| |
| − | -- table, extended if parsed
| |
| − | -- false, if invalid text format
| |
| − | local r
| |
| − | local s = analyse:match( "^(2%d%d%d) " )
| |
| − | local sx
| |
| − | if s then
| |
| − | -- ymd "10:28, 2013 Dez. 30"
| |
| − | local n = false
| |
| − | r = assign
| |
| − | r.year = tonumber( s )
| |
| − | s = analyse:sub( 6 )
| |
| − | s, sx = mw.ustring.match( analyse:sub( 6 ),
| |
| − | "^([%a&;]+)%.? (%d%d?)$" )
| |
| − | if s then
| |
| − | n = Parser.monthNumber( s )
| |
| − | if n then
| |
| − | r.month = n
| |
| − | end
| |
| − | end
| |
| − | if n then
| |
| − | r.dom = tonumber( sx )
| |
| − | r.dom2 = ( #sx == 2 )
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | else
| |
| − | -- dmy "10:28, 30. Dez. 2013"
| |
| − | local sep
| |
| − | s, sep, sx = analyse:match( "^(%d%d?)(%.? ?)(%a.+)$" )
| |
| − | if s then
| |
| − | r = Parser.european( s, sep, sx, assign )
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- Parser.wikiDate()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.yearTime = function ( analyse, assign )
| |
| − | -- String analysis, for possible year and possible time
| |
| − | -- Parameter:
| |
| − | -- analyse -- string, starting with year
| |
| − | -- assign -- table
| |
| − | -- Returns:
| |
| − | -- table, extended if parsed
| |
| − | -- false, if invalid text format
| |
| − | local r = assign
| |
| − | local n = #analyse
| |
| − | if n > 0 then
| |
| − | local s, sx
| |
| − | if n == 4 then
| |
| − | if analyse:match( "^%d%d%d%d$" ) then
| |
| − | s = analyse
| |
| − | sx = false
| |
| − | end
| |
| − | else
| |
| − | s = analyse:match( "^(%d%d%d%d)[ ,]" )
| |
| − | if s then
| |
| − | sx = analyse:sub( 5 )
| |
| − | else
| |
| − | local suffix
| |
| − | s, sx, suffix = analyse:match( "^(%d+)([ ,]?)(.*)$" )
| |
| − | if s then
| |
| − | local j = #sx
| |
| − | n = #s
| |
| − | if n < 4 and ( j == 1 or #suffix == 0 ) then
| |
| − | sx = analyse:sub( n + j )
| |
| − | else
| |
| − | s = false
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | if s then
| |
| − | r.year = tonumber( s )
| |
| − | if sx then
| |
| − | s, sx = sx:match( "^(,? ?)(%d.*)$" )
| |
| − | if #s >= 1 then
| |
| − | r = Parser.time( sx, r )
| |
| − | end
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- Parser.yearTime()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.zone = function ( analyse, assign )
| |
| − | -- String analysis, for time zone
| |
| − | -- +/-nn +/-nnnn (AAAa)
| |
| − | -- Parameter:
| |
| − | -- analyse -- string
| |
| − | -- assign -- table
| |
| − | -- Returns:
| |
| − | -- 1 -- table, with number or string zone, if any, or false
| |
| − | -- 2 -- string, with zone stripped off, if any
| |
| − | local rO = assign
| |
| − | local rS = analyse
| |
| − | local s, sign, shift, sub
| |
| − | s = "^(.+)([+-])([01]%d):?(%d?%d?)$"
| |
| − | s, sign, shift, sub = analyse:match( s )
| |
| − | if sign then
| |
| − | if s:find( ":%d%d *$" ) then
| |
| − | if sub then
| |
| − | if #sub == 2 then
| |
| − | rO.zone = tonumber( shift .. sub )
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | else
| |
| − | rO.zone = tonumber( shift ) * 100
| |
| − | end
| |
| − | if rO then
| |
| − | if sign == "-" then
| |
| − | rO.zone = - rO.zone
| |
| − | end
| |
| − | rS = mw.text.trim( s )
| |
| − | end
| |
| − | end
| |
| − | elseif analyse:find( "%(.*%)$" ) then
| |
| − | s, shift = analyse:match( "^(.+)%((%a%a%a%a?)%)$" )
| |
| − | if shift then
| |
| − | rO.zone = shift:upper()
| |
| − | rS = mw.text.trim( s )
| |
| − | else
| |
| − | rO = false
| |
| − | end
| |
| − | else
| |
| − | s, shift = analyse:match( "^(.+%d) ?(%a+)$" )
| |
| − | if shift then
| |
| − | local n = #shift
| |
| − | if n == 1 then
| |
| − | rO.zone = shift:upper()
| |
| − | elseif n == 3 then
| |
| − | if shift == "UTC" or shift == "GMT" then
| |
| − | rO.zone = 0
| |
| − | end
| |
| − | end
| |
| − | if rO.zone then
| |
| − | rS = s
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | return rO, rS
| |
| − | end -- Parser.zone()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Parser.GermanEnglish = function ( analyse )
| |
| − | -- String analysis, for German and English formats
| |
| − | -- Parameter:
| |
| − | -- analyse -- string, with date or time or parts of it
| |
| − | -- Returns:
| |
| − | -- table, if parsed
| |
| − | -- false, if invalid text format
| |
| − | local r, s = Parser.eraGermanEnglish( analyse )
| |
| − | r, s = Parser.zone( s, r )
| |
| − | if r then
| |
| − | local start, sep, sx = s:match( "^(%d+)([ %-%.:WwT]?)(.*)$" )
| |
| − | if start then
| |
| − | -- begins with one or more digits (ASCII)
| |
| − | local n = #start
| |
| − | local lazy = ( start == s and
| |
| − | ( n >=4 or type( r.bc == "boolean" ) ) )
| |
| − | if n == 4 or n == 8 or lazy then
| |
| − | r = Parser.digitsHeading( s, lazy, n, r )
| |
| − | elseif n <= 2 then
| |
| − | if sep == ":" then
| |
| − | r, s = Parser.time( s, r )
| |
| − | elseif sep == "" then
| |
| − | r = false
| |
| − | else
| |
| − | r = Parser.european( start, sep, sx, r )
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | else
| |
| − | local rM, sM = Parser.monthHeading( s, r )
| |
| − | if rM then
| |
| − | r = rM
| |
| − | else
| |
| − | r, sM = Parser.isoDate( s, r )
| |
| − | end
| |
| − | if r and sM ~= "" then
| |
| − | r = Parser.time( sM, r )
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- Parser.GermanEnglish()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Private.factory = function ( assign, alien, add )
| |
| − | -- Create DateTime table (constructor)
| |
| − | -- Parameter:
| |
| − | -- assign -- string, with initial timestamp, or nil
| |
| − | -- nil -- now
| |
| − | -- false -- empty object
| |
| − | -- alien -- string, with language code, or nil
| |
| − | -- add -- string, with interval (PHP strtotime), or nil
| |
| − | -- Returns:
| |
| − | -- table, for DateTime object
| |
| − | -- string or false, if failed
| |
| − | local l = true
| |
| − | local slang = mw.text.trim( alien or World.slang or "en" )
| |
| − | local r
| |
| − | if assign == false then
| |
| − | r = { }
| |
| − | else
| |
| − | local stamp = ( assign or "now" )
| |
| − | local shift
| |
| − | if add then
| |
| − | shift = Private.future( add )
| |
| − | end
| |
| − | r = false
| |
| − | if stamp == "now" then
| |
| − | stamp = frame():callParserFunction( "#timel", "c", shift )
| |
| − | shift = false
| |
| − | else
| |
| − | local seconds = stamp:match( "^#(%d+)$" )
| |
| − | if seconds then
| |
| − | stamp = os.date( "!%Y-%m-%dT%H:%M:%S",
| |
| − | tonumber( seconds ) )
| |
| − | end
| |
| − | end
| |
| − | l, r = pcall( Private.fetch, stamp, slang, shift )
| |
| − | end
| |
| − | if l and type( r ) == "table" then
| |
| − | if slang ~= "" then
| |
| − | r.lang = slang
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- Private.factory()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Private.fetch = function ( analyse, alien, add )
| |
| − | -- Retrieve object from string
| |
| − | -- Parameter:
| |
| − | -- analyse -- string to be interpreted
| |
| − | -- alien -- string with language code, or nil
| |
| − | -- add -- string, with interval (PHP strtotime), or nil
| |
| − | -- Returns:
| |
| − | -- table, if parsed
| |
| − | -- false, if invalid text format
| |
| − | -- string, if serious error (args)
| |
| − | local r
| |
| − | if type( analyse ) == "string" then
| |
| − | r = analyse:gsub( " ", " " )
| |
| − | :gsub( " ", " " )
| |
| − | :gsub( "&#x[aA]0;", " " )
| |
| − | :gsub( " ", " " )
| |
| − | :gsub( Nbsp, " " )
| |
| − | :gsub( Tab, " " )
| |
| − | :gsub( " +", " " )
| |
| − | :gsub( "%[%[", "" )
| |
| − | :gsub( "%]%]", "" )
| |
| − | r = mw.text.trim( r )
| |
| − | if r == "" then
| |
| − | r = { }
| |
| − | else
| |
| − | local slang = ( alien or "" )
| |
| − | if slang == "" then
| |
| − | slang = "en"
| |
| − | else
| |
| − | local s = slang:match( "^(%a+)%-" )
| |
| − | if s then
| |
| − | slang = s
| |
| − | end
| |
| − | end
| |
| − | slang = slang:lower()
| |
| − | if slang == "en" or slang == "de" then
| |
| − | local l
| |
| − | l, r = pcall( Parser.GermanEnglish, r )
| |
| − | if l and r then
| |
| − | if not Prototypes.fair( r ) then
| |
| − | r = false
| |
| − | elseif add then
| |
| − | r = Prototypes.future( r, add )
| |
| − | end
| |
| − | end
| |
| − | else
| |
| − | r = "unknown language"
| |
| − | end
| |
| − | end
| |
| − | else
| |
| − | r = "bad type"
| |
| − | end
| |
| − | return r
| |
| − | end -- Private.fetch()
| |
| − |
| |
| − |
| |
| − |
| |
| − | 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
| |
| − | else
| |
| − | r = nil
| |
| − | end
| |
| − | if r ~= 0 then
| |
| − | if at1.bc and r then
| |
| − | r = r * -1
| |
| − | end
| |
| − | break -- for i
| |
| − | end
| |
| − | life = true
| |
| − | end
| |
| − | end -- for i
| |
| − | end
| |
| − | return r
| |
| − | end -- Private.flow()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Private.foreign = function ()
| |
| − | -- Retrieve localization submodule
| |
| − | if not Meta.localized then
| |
| − | local l, d = pcall( mw.loadData, "Module:DateTime/local" )
| |
| − | if l then
| |
| − | local wk
| |
| − | if d.slang then
| |
| − | Meta.suite = string.format( "%s %s",
| |
| − | Meta.suite, d.slang )
| |
| − | World.slang = d.slang
| |
| − | end
| |
| − | for k, v in pairs( d ) do
| |
| − | wk = World[ k ]
| |
| − | if wk and wk.en then
| |
| − | for subk, subv in pairs( v ) do
| |
| − | wk[ subk ] = subv
| |
| − | end -- for k, v%s %s
| |
| − | else
| |
| − | World[ k ] = v
| |
| − | end
| |
| − | end -- for k, v
| |
| − | end
| |
| − | Meta.localized = true
| |
| − | end
| |
| − | end -- Private.foreign()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Private.from = function ( attempt )
| |
| − | -- Create valid raw table from arbitrary table
| |
| − | -- Parameter:
| |
| − | -- attempt -- table, to be evaluated
| |
| − | -- Returns:
| |
| − | -- table, with valid components, or nil
| |
| − | local data = { }
| |
| − | local r
| |
| − | for k, v in pairs( Meta.components ) do
| |
| − | if v then
| |
| − | v = ( type( attempt[ k ] ) == v )
| |
| − | else
| |
| − | v = true
| |
| − | end
| |
| − | if v then
| |
| − | data[ k ] = attempt[ k ]
| |
| − | end
| |
| − | end -- for k, v
| |
| − | if Prototypes.fair( data ) then
| |
| − | r = data
| |
| − | end
| |
| − | return r
| |
| − | end -- Private.from()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Private.future = function ( add )
| |
| − | -- Normalize move interval
| |
| − | -- Parameter:
| |
| − | -- add -- string or number, to be added
| |
| − | -- Returns:
| |
| − | -- string, with shift, or false/nil
| |
| − | local r
| |
| − | if add then
| |
| − | local s = type( add )
| |
| − | if s == "string" and add:match( "^%s*[+-]?%d+%.?%d*%s*$" ) then
| |
| − | r = tonumber( add )
| |
| − | s = "number"
| |
| − | else
| |
| − | r = add
| |
| − | end
| |
| − | if s == "number" then
| |
| − | if r == 0 then
| |
| − | r = false
| |
| − | else
| |
| − | r = string.format( "%d second", r )
| |
| − | end
| |
| − | elseif s ~= "string" then
| |
| − | r = false
| |
| − | end
| |
| − | if r then
| |
| − | r = Calc.future( r )
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- Private.future()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Prototypes.clone = function ( self )
| |
| − | -- Clone object
| |
| − | -- Parameter:
| |
| − | -- self -- table, with object, to be cloned
| |
| − | -- Returns:
| |
| − | -- table, with object
| |
| − | local r = { [ Meta.signature ] = self[ Meta.signature ] }
| |
| − | setmetatable( r, Meta.tableI )
| |
| − | return r
| |
| − | end -- Prototypes.clone()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Prototypes.fair = function ( self, access, assign )
| |
| − | -- Check formal validity of table
| |
| − | -- Parameter:
| |
| − | -- self -- table, to be checked
| |
| − | -- access -- string or nil, single item to be checked
| |
| − | -- assign -- single access value to be checked
| |
| − | -- Returns:
| |
| − | -- true, if valid; false, if not
| |
| − | local r = ( type( self ) == "table" )
| |
| − | if r then
| |
| − | local defs = { year = { max = MaxYear },
| |
| − | month = { min = 1,
| |
| − | max = 12 },
| |
| − | week = { min = 1,
| |
| − | max = 53 },
| |
| − | dom = { min = 1,
| |
| − | max = 31 },
| |
| − | hour = { max = 23 },
| |
| − | min = { max = 59 },
| |
| − | sec = { max = 61 },
| |
| − | msec = { max = 999 },
| |
| − | mysec = { max = 999 }
| |
| − | }
| |
| − | local fNum =
| |
| − | function ( k, v )
| |
| − | local ret = true
| |
| − | local dk = defs[ k ]
| |
| − | if dk then
| |
| − | if type( dk.max ) == "number" then
| |
| − | ret = ( type( v ) == "number" )
| |
| − | if ret then
| |
| − | local min
| |
| − | if dk.min then
| |
| − | min = dk.min
| |
| − | else
| |
| − | min = 0
| |
| − | end
| |
| − | ret = ( v >= min and v <= dk.max
| |
| − | and math.floor( v ) == v )
| |
| − | if ret and dk.f then
| |
| − | ret = dk.f( v )
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | return ret
| |
| − | end -- fNum()
| |
| − | defs.dom.f =
| |
| − | function ()
| |
| − | local ret
| |
| − | local d
| |
| − | if access == "dom" then
| |
| − | d = assign
| |
| − | else
| |
| − | d = self.dom
| |
| − | end
| |
| − | if d then
| |
| − | ret = ( d <= 28 )
| |
| − | if not ret then
| |
| − | local m
| |
| − | if access == "month" then
| |
| − | m = assign
| |
| − | else
| |
| − | m = self.month
| |
| − | end
| |
| − | if m then
| |
| − | ret = ( d <= Calc.months[ m ] )
| |
| − | if ret then
| |
| − | local y
| |
| − | if access == "year" then
| |
| − | y = assign
| |
| − | else
| |
| − | y = self.year
| |
| − | end
| |
| − | if d == 29 and m == 2 and y then
| |
| − | if y % 4 ~= 0 or y % 400 == 0 then
| |
| − | ret = false
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | else
| |
| − | ret = true
| |
| − | end
| |
| − | return ret
| |
| − | end -- defs.dom.f()
| |
| − | defs.sec.f =
| |
| − | function ()
| |
| − | local ret
| |
| − | local second
| |
| − | if access == "sec" then
| |
| − | second = assign
| |
| − | else
| |
| − | second = self.sec
| |
| − | end
| |
| − | if second then
| |
| − | ret = ( second <= 59 )
| |
| − | if not ret and self.leap then
| |
| − | ret = true
| |
| − | end
| |
| − | end
| |
| − | return ret
| |
| − | end -- defs.sec.f()
| |
| − | if access or assign then
| |
| − | r = ( type( access ) == "string" )
| |
| − | if r then
| |
| − | 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
| |
| − | else
| |
| − | local life = false
| |
| − | 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 -- for i
| |
| − | if self.week and ( self.month or self.dom ) then
| |
| − | r = false
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- Prototypes.fair()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Prototypes.figure = function ( self, assign )
| |
| − | -- Assign month by name
| |
| − | -- Parameter:
| |
| − | -- self -- table, to be filled
| |
| − | -- assign -- string, with month name
| |
| − | -- Returns:
| |
| − | -- number 1...12, if valid; false, if not
| |
| − | local r = false
| |
| − | if type( self ) == "table" and type( assign ) == "string" then
| |
| − | r = Parser.monthNumber( assign )
| |
| − | if r then
| |
| − | self.month = r
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- Prototypes.figure()
| |
| − |
| |
| − |
| |
| − |
| |
| − | 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
| |
| − | local n = brief.n or 3
| |
| − | r = mw.ustring.sub( r, 1, n )
| |
| − | end
| |
| − | if s then
| |
| − | r = r .. s
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | else
| |
| − | r = false
| |
| − | end
| |
| − | return r
| |
| − | end -- Prototypes.first()
| |
| − |
| |
| − |
| |
| − |
| |
| − | 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
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- Prototypes.flow()
| |
| − |
| |
| − |
| |
| − |
| |
| − | Prototypes.format = function ( self, ask, adapt )
| |
| − | -- Format object as string
| |
| − | -- Parameter:
| |
| − | -- self -- 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 false, if invalid
| |
| − | local r = false
| |
| − | if type( self ) == "table" then
| |
| − | local opts = { lang = self.lang }
| |
| − | local babel, slang
| |
| − | 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.lang = opts.lang
| |
| − | opts.london = adapt.london
| |
| − | opts.lonely = adapt.lonely
| |
| − | end
| |
| − | babel = mw.language.new( opts.lang )
| |
| − | if babel then
| |
| − | local shift, show, stamp, suffix, limit4, locally
| |
| − | if self.month then
| |
| − | stamp = World.monthsLong.en[ self.month ]
| |
| − | if self.year then
| |
| − | stamp = string.format( "%s %04d", stamp, self.year )
| |
| − | end
| |
| − | if self.dom then
| |
| − | stamp = string.format( "%d %s", self.dom, stamp )
| |
| − | end
| |
| − | if ask and ask:find( "Mon4" ) then
| |
| − | local mon4 = World.months4[ opts.lang ]
| |
| − | if mon4 then
| |
| − | if mon4[ self.month ] then
| |
| − | limit4 = true
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | 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.%03d",
| |
| − | stamp, self.msec )
| |
| − | if self.mysec then
| |
| − | stamp = string.format( "%s%03d",
| |
| − | stamp,
| |
| − | self.mysec )
| |
| − | end
| |
| − | 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( " $", "" )
| |
| − | 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:
| |
| − | -- 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
| |
| − | raw = r[ Meta.signature ]
| |
| − | rel = Private.future( shift )
| |
| − | 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, 4 do
| |
| − | f( i )
| |
| − | end -- for i
| |
| − | r = s
| |
| − | s = ""
| |
| − | for i = 5, 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
| |
| − | 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"
| |
| − | 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
| |
| − | 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( "^ ", "" )
| |
| − | 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( "^ ", "" )
| |
| − | 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" ) then
| |
| − | if stamp then
| |
| − | r1 = string.format( "%s %s", r1, stamp )
| |
| − | end
| |
| − | 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 %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 )
| |
| − | 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
| |
| − | 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 = { }
| |
| − |
| |
| − | function p.test( args, alien )
| |
| − | local slang = args.lang
| |
| − | local obj = Meta.fiat( args[ 1 ], false, args.shift )
| |
| − | local r
| |
| − | if type( obj ) == "table" then
| |
| − | local spec = args[ 2 ]
| |
| − | local opt
| |
| − | if spec then
| |
| − | spec = mw.text.trim( spec )
| |
| − | end
| |
| − | if slang then
| |
| − | opt = { lang = mw.text.trim( slang ) }
| |
| − | end
| |
| − | r = obj:format( spec, opt )
| |
| − | else
| |
| − | r = ( args.noerror or "0" )
| |
| − | if r == "0" then
| |
| − | r = fault( "Format nicht erkannt" )
| |
| − | else
| |
| − | r = ""
| |
| − | end
| |
| − | end
| |
| − | return r
| |
| − | end -- p.test
| |
| − |
| |
| − |
| |
| − |
| |
| − | function p.failsafe( frame )
| |
| − | local s = type( frame )
| |
| − | local r, 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
| |
| − | if since then
| |
| − | if since > Meta.serial then
| |
| − | r = ""
| |
| − | else
| |
| − | r = Meta.serial
| |
| − | end
| |
| − | else
| |
| − | r = Meta.serial
| |
| − | end
| |
| − | return r
| |
| − | end -- p.failsafe
| |
| − |
| |
| − |
| |
| − |
| |
| − | function p.format( 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 }
| |
| − | 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.lt( frame )
| |
| − | return Templates.flow( frame, "lt" )
| |
| − | end -- p.lt
| |
| − | function p.le( frame )
| |
| − | return Templates.flow( frame, "le" )
| |
| − | end -- p.le
| |
| − | function p.eq( frame )
| |
| − | return Templates.flow( frame, "eq" )
| |
| − | end -- p.eq
| |
| − | function p.ne( frame )
| |
| − | return Templates.flow( frame, "ne" )
| |
| − | end -- p.ne
| |
| − | function p.ge( frame )
| |
| − | return Templates.flow( frame, "ge" )
| |
| − | end -- p.ge
| |
| − | function p.gt( frame )
| |
| − | return Templates.flow( frame, "gt" )
| |
| − | end -- p.gt
| |
| − |
| |
| − |
| |
| − |
| |
| − | p.DateTime = function ()
| |
| − | return DateTime
| |
| − | end -- p.DateTime
| |
| − |
| |
| − | return p
| |