Modul:Wikidata/Time

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen
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
				Time:qualified(snak)	snak and qualification state
				Time:isLessthan(time)	comparator method
				Time:equals(time)		comparator method
* service.LT(a, b)			comparator function for table.sort e.g.
* service.equals(a, b)		comparator function
* service.timify(values)	table of time objects by table of values

== for use in templates ==

{{#invoke:Wikidata/Time|now|<format string>}}	current system time
			(mainly for testing purposes;
			 format string optional: defaults to wikidata time string format)

]=]
	
--Module globals

local _, GeneralTime = pcall(require, "Modul:Time")
local constant = GeneralTime.constant
local pointOfTime = GeneralTime.point

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 = constant.PRECISIONLEVEL,
	DEFAULTFORMAT = constant.DEFAULTFORMAT,
	PoT='point of time'
} }

local _, DateTime = pcall(require, "Modul:DateTime")

--------------------------- 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)
	mw.log(source)
	mw.log(type(source))
	-- time object is UTC system time if no source specified
	if not source or source == '' then
		return pointOfTime:new()
	end
	if type(source) == "table" then
		mw.logObject(source, 'from table')
		local ts = source["time"]
		if not ts then return pointOfTime:new(source) end
		o = {}
		setmetatable(o, {__index = pointOfTime})
		self.__index = self
		o.era, o.year, o.month, o.day, o.hour, o.min, o.sec
			= ts:match(p.service.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
		o.__tostring=function()
			return o:format()
		end
	elseif type(source) == 'string' then return pointOfTime:new(source) end
	return o
end

--[[
	Time:qualified(Statement)
	Statement and its qualification state
	parameters:
		Statement	a Statement that is to be qualified
	returns:	Statement, true		if this time qualifies the snack
				Statement, false	if Statement is independent from this time
				nil, false			if this time disqualifies the snack
				nil, true			if Statement is nil (Ex falso quodlibet)
]]
p.service.qualified = function(this, Statement)
	if not snack then return nil, true end
	if type(Statement) ~= 'table' then return Statement, false end
	if not Statement.qualifiers then return Statement, false end
	local hasCriteria = false
	-- point of time
	for _, pot in ipairs(Statement.qualifiers.P585) do
		local comp = p.service:new(pot.datavalue.value)
		if this ~= comp then return nil, false end
		hasCriteria = true;
	end
	-- start time
	for _, pot in ipairs(Statement.qualifiers.P580) do
		local comp = p.service:new(pot.datavalue.value)
		if this < comp then return nil, false end
		hasCriteria = true;
	end
	-- end time
	for _, pot in ipairs(Statement.qualifiers.P582) do
		local comp = p.service:new(pot.datavalue.value)
		if comp < this then return nil, false end
		hasCriteria = true;
	end
	return Statement, hasCriteria
end

--[[
	Time:getFiltered(statemens)
	new claim list without time disqualified claims
	parameters:
		statemens	data source as of mw.wikidata.getBestStatements
	returns:	refined claimlist
]]
p.service.getFiltered = function(this, statements)
	local result = {}
	for _, v in ipairs(claimlist) do
		local tested, tv = this:qualified(v)
		if tested then table.insert(result, tested) end
	end
	return result
end

--[[
	Time.timify(values)
	table of time objects by table of values
	can process statements as of mw.wikidata.getBestStatements('Q79822', 'P569')
	or qualifiers for a statement
	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 value = v
		if value.mainsnak then value = value.mainsnak end
		if value.datavalue then value = value.datavalue end
		if value.value then value = value.value end
		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

--[[
	Time.filtered(claimlist, timeStr)
	new claim list without time disqualified claims
	parameters:
		claimlist	data source as of mw.wikidata.getBestStatements
		timeStr		time given by user
	returns:	refined claimlist
]]
p.service.filtered = function(statements, timeStr)
	local myTime = p.service:new(timeStr)
	return myTime:getFiltered(statements)
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

local testLine = function(a, b, c)
	local result = '<tr style="background-color:'
	if type(b) == 'boolean' then if b then b = 'true' else b = 'false' end
	elseif b == nil then b = 'nil'
	elseif type(b) == 'table' then
		local t = b.format
		if t then b = t(b) end
	end
	if type(c) == 'boolean' then if c then c = 'true' else c = 'false' end
	elseif c == nil then c = 'nil'
	elseif type(c) == 'table' then
		local t = c.format
		if t then c = t(c) end
	end
	if b == c then result = result .. '#4f4">'
	else result = result .. '#f44">' end
	return	result .. '<td>' .. a .. '</td><td>' .. b .. '</td><td>' .. c
		..	'</td></tr>'
end

p.test = function()
	local result = '<table class="wikitable">'
	local a = p.service:new('1.3.2000')
	mw.logObject(a)
	result = result .. testLine("a:format('mm-dd')", a:format('mm-dd'), '03-01')
	local b = constant.STARTOFGREGORIAN
	result = result .. testLine("a, b", a, b)
	result = result .. testLine("a < b", a < b, false)
	result = result .. testLine("a > b", a > b, true)
	result = result .. testLine("a == b", a == b, false)
	result = result .. testLine("a ~= b", a ~= b, true)
	a = p.service:new('1582-08-15')
	result = result .. testLine("a, b", a, b)
	result = result .. testLine("a < b", a < b, false)
	result = result .. testLine("a == b", a == b, true)
	result = result .. testLine("a ~= b", a ~= b, false)
	a = p.service:new()
	result = result .. testLine("today", a:format('d.m.yyyy'), '2.11.2022')
	result = result .. testLine("day of the week", a:dayOfTheWeek(), 4)
	result = result .. testLine("day of the week", b:dayOfTheWeek(), 2)
	a = p.service:new('1582-08-04')
	result = result .. testLine("day of the week", a:dayOfTheWeek(), 1)
	return result .. '</table>'
end

return p