Modul:Time
Erscheinungsbild
Vorlagenprogrammierung | Diskussionen | Lua | Unterseiten | |||
Modul | Deutsch | English
|
Modul: | Dokumentation |
Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus
--[=[ Time 2022-10-31
Modul for processing time information; point and span objects
Author: Vollbracht
== for use in other modules ==
* constant.PRECISIONLEVEL table of valid precision values
constants:
MIN lowest valid precision level (value for t.precision)
MINUSE lowest index of PRECISIONLEVEL table
MAX highest valid precision level
[MINUSE] .. [MAX] precision level name (unit)
function
unit(level) unit name of smallest significant time element
* point object representing a point of time
fields: year, month, day, hour, min, sec,
precision, timezone, calendarmodel
constructor:
Time:new(value) processes snack.datavalue.value e.g.
method:
Time:format(fmtStr) string representation for time object
Time:isLessthan(time) comparator method
Time:equals(time) comparator method
]=]
local p = {
constant = {
PRECISIONLEVEL = {
MIN = 0, -- lowest valid precision
MINUSE = 9, -- lowest available index
MAXUSE = 14, -- highest valid precision
MAX=15, -- highest available index
-- unused: 'E8', 'E7', 'E6', 'E5', 'E4',
-- [6]='millennium', [7]='century', [8]='decade',
[9]='year', [10]='month', [11]='day',
[12]='hour', [13]='min', [14]='sec', [15]='msec',
},
DEFAULTFORMAT = {
[6]='yyyye=( v.Chr.)', [7]='yyyye=( v.Chr.)', [9]='yyyye=( v.Chr.)',
[9]='yyyye=( v.Chr.)', [10]='mm/yyyy', [11]='dd.mm.yyyy', [12]='HH Uhr',
[13]='HH:MM Uhr', [14]='E=(+)e=(-)yyyy-mm-ddTHH:MM:SSZ'
}
},
point = {},
duration = {}
}
--[[
p.constant.PRECISIONLEVEL
constant constructor:
]]
local precisionlevel = function()
o = {}
setmetatable(o, p.constant.PRECISIONLEVEL)
o.__index = function(table, key)
return p.constant.PRECISIONLEVEL[key]
end
o.unit = function(this, level)
if level < o.MIN then return '' end
if level < o.MINUSE then return o[o.MINUSE] end
if level > o.MAXUSE then return o[o.MAXUSE] end
local result = o[i]
if result then return result end
end
return o
end
---------------------- point ----------------------
-- Point of time
----------------------
--[[
constructor
parameter:
timeStr: string that can be processed by
mw.language.getContentLanguage():formatDate
]]
function p.point:new(timeStr)
local myTime = nil
if timeStr then
local o = {}
setmetatable(o, self)
self.__index = self
local fsIn = "+Y-m-d\\TH:i:s\\Z"
local fsOut = "(.)(%d+)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)Z"
local t = mw.language.getContentLanguage():formatDate(fsIn, timeStr)
o.era, o.year, o.month, o.day, o.hour, o.min, o.sec = t:match(fsOut)
if t:match('00:00:00Z') then o.precision = 11
elseif t:match('00:00Z') then o.precision = 12
elseif t:match('00Z') then o.precision = 13
else o.precision = 14
end
return o
else
local d = os.date("!*t")
for k, v in pairs(p.service) do d[k] = v end
d.era = '+'
d.precision = 14
d.timezone = 0
d.calendarmodel = "http://www.wikidata.org/entity/Q1985727"
return d
end
end
--[[
pointOfTime:format(fmtStr)
return formated date time value based on given format string
parameters:
fmtStr: limited format string evaluating each appearance of keys:
either
%y or %Y for year
%m for month
%d for day of month
%H for 24-hour hour value
%M for minute
%S for second
or
yy or yyyy for year
m or mm for month
d or dd for day of month
H or HH for 24-hour hour value
M or MM for minute
S or SS for second
e=(<content>) for content string appearing
if era is '-' (BC)
E=(<content>) for content string appearing
if era is '+' (CE)
returns date time value string with all requested information or ''
]]
p.point.format = function(this, fmtStr)
function d2(value)
if value > 9 then return value end
return '0' .. value
end
if not fmtStr then
if this.precision then
fmtStr = p.const.DEFAULTFORMAT[this.precision]
if not fmtStr then return '' end
else return '' end
end
if fmtStr:match('%%') then
if this.year then
fmtStr = fmtStr:gsub('%%Y', this.year)
if this.year < 100 then fmtStr = fmtStr:gsub('%%y', this.year)
else fmtStr = fmtStr:gsub('%%y', d2(this.year % 100)) end
else
if fmtStr:match('%%[yY]') then return '' end
end
if this.month then fmtStr = fmtStr:gsub('%%m', d2(this.month))
else if fmtStr:match('%%m') then return '' end end
if this.month then fmtStr = fmtStr:gsub('%%d', d2(this.day))
else if fmtStr:match('%%d') then return '' end end
if this.month then fmtStr = fmtStr:gsub('%%H', d2(this.hour))
else if fmtStr:match('%%H') then return '' end end
if this.month then fmtStr = fmtStr:gsub('%%M', d2(this.min))
else if fmtStr:match('%%M') then return '' end end
if this.month then fmtStr = fmtStr:gsub('%%S', d2(this.sec))
else if fmtStr:match('%%S') then return '' end end
else
if this.year then
fmtStr = fmtStr:gsub('yyyy', this.year)
fmtStr = fmtStr:gsub('jjjj', this.year)
if this.year < 100 then
fmtStr = fmtStr:gsub('yy', this.year)
fmtStr = fmtStr:gsub('jj', this.year)
else
fmtStr = fmtStr:gsub('yy', d2(this.year % 100))
fmtStr = fmtStr:gsub('jj', d2(this.year % 100))
end
else if fmtStr:match('[jy][jy]') then return '' end end
if this.month then
fmtStr = fmtStr:gsub('mm', d2(this.month))
fmtStr = fmtStr:gsub('m', this.month)
else if fmtStr:match('m') then return '' end end
if this.day then
fmtStr = fmtStr:gsub('dd', d2(this.day))
fmtStr = fmtStr:gsub('tt', d2(this.day))
fmtStr = fmtStr:gsub('d', this.day)
fmtStr = fmtStr:gsub('t', this.day)
else if fmtStr:match('[dt]') then return '' end end
if this.hour then
fmtStr = fmtStr:gsub('HH', d2(this.hour))
fmtStr = fmtStr:gsub('H', this.hour)
else if fmtStr:match('H') then return '' end end
if this.min then
fmtStr = fmtStr:gsub('MM', d2(this.min))
fmtStr = fmtStr:gsub('M', this.min)
else if fmtStr:match('M') then return '' end end
if this.sec then
fmtStr = fmtStr:gsub('SS', d2(this.sec))
fmtStr = fmtStr:gsub('S', this.sec)
else if fmtStr:match('S') then return '' end end
if this.era then
if this.era == '+' then
fmtStr = fmtStr:gsub('e=%(.*%)', '')
fmtStr = fmtStr:gsub('E=%((.*)%)', '%1')
else
fmtStr = fmtStr:gsub('E=%(.*%)', '')
fmtStr = fmtStr:gsub('e=%((.*)%)', '%1')
end
end
end
return fmtStr
end
--[[
pointOfTime.isLessthan(a, b)
datetime compare
parameters:
a, b 2 service.time objects
returns: true if on lowest precision level a is before b
false if necessary properties inavailable or
if a is same time or later than b on given
precision level
]]
p.point.isLessthan = function(a, b)
if not a then return false end
if not b then return false end
local precision = 11
if a.precision then precision = a.precision end
if b.precision and b.precision < precision then
precision = b.precision
end
if a.era and b.era then
if a.era ~= b.era then return b.era == '+' end
if a.year and b.year then
local na = tonumber(a.year)
local nb = tonumber(b.year)
if na ~= nb then return (a.era == '+') == (na < nb) end
else return false end
end
for i = 10, 14 do
if precision < i then return false end
local aa = a[p.service.PRECISIONLEVEL[i]]
local ab = b[p.service.PRECISIONLEVEL[i]]
if aa and ab then
local na = tonumber(aa)
local nb = tonumber(ab)
if na ~= nb then return na < nb end
else return false end
i = i + 1
end
return false
end
--[[
pointOfTime.LT(a, b)
comparator function for sort e.g.
]]
p.point.LT = function(a, b)
if a.time then a = a.time end
if b.time then b = b.time end
if not a.isLessthan then return false end
return a.isLessthan(b)
end
--[[
pointOfTime.LE(a, b)
comparator function
]]
p.point.LE = function(a, b)
if a.time then a = a.time end
if b.time then b = b.time end
if not b.isLessthan then return false end
return not b.isLessthan(a)
end
--[[
pointOfTime.GT(a, b)
comparator function
]]
p.point.GT = function(a, b)
if a.time then a = a.time end
if b.time then b = b.time end
if not b.isLessthan then return false end
return b.isLessthan(a)
end
--[[
pointOfTime.LE(a, b)
comparator function
]]
p.point.GE = function(a, b)
if a.time then a = a.time end
if b.time then b = b.time end
if not a.isLessthan then return false end
return not a.isLessthan(b)
end
--[[
Time.equals(a, b)
compares any objects in terms of time properties
parameters: two of any kind
returns: true * if both objects represent the same time at lowest
common precision level
* if both objects lack the same time properties
* if both are no objects but of simple data type
false * if the objects represent different times at lowest
common precision level
* if only one lacks a relevant time property
* if only one is of simple data type even if the other
doesn't contain time properties at all
]]
p.service.equals = function(a, b)
if not a == not b then return true end
if not a then return false end
if not b then return false end
if type(a) ~= 'table' then return type (b) == 'table' end
if type (b) ~= 'table' then return false end
local precision = 11
if a.precision then precision = a.precision end
if b.precision and b.precision < precision then
precision = b.precision
end
if a.era then
if a.era == '+' then
if b.era and b.era ~= '+' then return false end
else
if b.era then
if b.era == '+' then return false end
else return false end
end
else
if b.era and b.era ~= '+' then return false end
end
if precision < 9 then precision = 9 end
for i = 9, precision do
local aa = a[p.service.PRECISIONLEVEL[i]]
local ab = b[p.service.PRECISIONLEVEL[i]]
if not aa ~= not ab then return false end
if aa and aa ~= ab then return false end
i = i + 1
end
return true
end
return p