Modul:Wikidata/Time
Erscheinungsbild
Vorlagenprogrammierung | Diskussionen | Lua | Unterseiten | |
Modul | Deutsch
|
Modul: | Dokumentation |
Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus
--[=[ Wikidata/Time 2022-10-28
Module for processing wikidata time information
Author: Vollbracht
== for use in other modules ==
* service object representing a wikidata time property
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
function:
Time.lessthan comparator function for sort e.g.
Time.timify(values) table of time objects by table of values
== for use in templates ==
]=]
--Module globals
local p = { service={
-- more selective variant to '(.)(%d+)%-(%d+)%-(%d+)T(%d+):(%d+):(%d+)Z':
MATCHING = '(.)(%d+)%-([0-1]%d)%-([0-3]%d)T([0-2]%d):([0-6]%d):([0-6]%d)Z',
PRECISIONLEVEL = {
-- unused:
'E8', 'E7', 'E6', 'E5', 'E4',
-- use with caution (only 'year' is in time object) :
[6]='millennium', [7]='century', [8]='decade', [9]='year',
-- use at will (fields in time object):
[10]='month', [11]='day', [12]='hour', [13]='min', [14]='sec'
},
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'
},
} }
--------------------------- local functions -----------------------------
--------------------------- service functions -----------------------------
--[[
constructor
generates a Time object
parameters:
source: (optional) table of possible time informations as of
mw.wikibase.getBestStatements(a, b)[1].mainsnak.datavalue.value
current system time if nil
NO MANDANTORY INFOS IN TABLE! OBJECT MAY CONTAIN NO TIME DATA!
]]
function p.service:new(source)
-- time object is UTC system time if no source specified
if not source or source == '' then
d = os.date("!*t")
for k, v in pairs(p.service) do d[k] = v end
d.precision = 14
d.timezone = 0
d.calendarmodel = "http://www.wikidata.org/entity/Q1985727"
return d
end
o = {}
setmetatable(o, self)
self.__index = self
if type(source) == "table" then
local ts = source["time"]
if not ts then return o end
o.era, o.year, o.month, o.day, o.hour, o.min, o.sec
= ts:match(o.MATCHING)
o.year = tonumber(o.year)
o.month = tonumber(o.month)
o.day = tonumber(o.day)
o.hour = tonumber(o.hour)
o.min = tonumber(o.min)
o.sec = tonumber(o.sec)
o.precision = source.precision
o.timezone = source.timezone
o.calendarmodel = source.calendarmodel
end
return o
end
--[[
Time.lessthan(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.service.lessthan = 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
--[[
Time: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
]]
p.service.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 = this.DEFAULTFORMAT[this.precision]
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
end
if this.month then fmtStr = fmtStr:gsub('%%m', d2(this.month)) end
if this.month then fmtStr = fmtStr:gsub('%%d', d2(this.day)) end
if this.month then fmtStr = fmtStr:gsub('%%H', d2(this.hour)) end
if this.month then fmtStr = fmtStr:gsub('%%M', d2(this.min)) end
if this.month then fmtStr = fmtStr:gsub('%%S', d2(this.sec)) 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
end
if this.month then
fmtStr = fmtStr:gsub('mm', d2(this.month))
fmtStr = fmtStr:gsub('m', this.month)
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)
end
if this.hour then
fmtStr = fmtStr:gsub('HH', d2(this.hour))
fmtStr = fmtStr:gsub('H', this.hour)
end
if this.min then
fmtStr = fmtStr:gsub('MM', d2(this.min))
fmtStr = fmtStr:gsub('M', this.min)
end
if this.sec then
fmtStr = fmtStr:gsub('SS', d2(this.sec))
fmtStr = fmtStr:gsub('S', this.sec)
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
--[[
Time.timify(values)
table of time objects by table of values
parameters:
values: table: {<source>, <source>, ...}
<source>: (requirements as of time:new() source parameter)
returns: table: {<time object>, <time object>, ...}
Time objects of <source>-elements that could be
converted are in this result table. The others are
just ignored. Hence contains initialized time
objects only.
nil if result table empty
]]
p.service.timify = function(values)
local result = {}
for _, v in ipairs(values) do
local t = service.time:new(v)
if t.year then table.insert(result, t) end
end
if #result == 0 then return nil end
return result
end
--------------------------- template functions -----------------------------
--[[
{{#invoke:Wikidata/Time|now|<format string>}}
current system time
]]
p.now = function(frame)
return p.service:new():format(frame.args[1])
end
return p