<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://skandinavien-wiki.net/w/index.php?action=history&amp;feed=atom&amp;title=Modul%3AHours</id>
	<title>Modul:Hours - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://skandinavien-wiki.net/w/index.php?action=history&amp;feed=atom&amp;title=Modul%3AHours"/>
	<link rel="alternate" type="text/html" href="https://skandinavien-wiki.net/w/index.php?title=Modul:Hours&amp;action=history"/>
	<updated>2026-05-14T07:37:36Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in skandinavien-wiki.net</subtitle>
	<generator>MediaWiki 1.39.10</generator>
	<entry>
		<id>https://skandinavien-wiki.net/w/index.php?title=Modul:Hours&amp;diff=9786&amp;oldid=prev</id>
		<title>Xineohp1506: 1 Version von :wikivoyage:Modul:Hours importiert</title>
		<link rel="alternate" type="text/html" href="https://skandinavien-wiki.net/w/index.php?title=Modul:Hours&amp;diff=9786&amp;oldid=prev"/>
		<updated>2023-01-19T12:53:02Z</updated>

		<summary type="html">&lt;p&gt;1 Version von &lt;a href=&quot;https://de.wikivoyage.org/wiki/Modul:Hours&quot; class=&quot;extiw&quot; title=&quot;wikivoyage:Modul:Hours&quot;&gt;wikivoyage:Modul:Hours&lt;/a&gt; importiert&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 19. Januar 2023, 14:53 Uhr&lt;/td&gt;
				&lt;/tr&gt;
&lt;!-- diff cache key d03bbfb2:diff::1.12:old-9785:rev-9786 --&gt;
&lt;/table&gt;</summary>
		<author><name>Xineohp1506</name></author>
	</entry>
	<entry>
		<id>https://skandinavien-wiki.net/w/index.php?title=Modul:Hours&amp;diff=9785&amp;oldid=prev</id>
		<title>wikivoyage&gt;RolandUnger: require( &#039;strict&#039; )</title>
		<link rel="alternate" type="text/html" href="https://skandinavien-wiki.net/w/index.php?title=Modul:Hours&amp;diff=9785&amp;oldid=prev"/>
		<updated>2022-10-22T15:07:46Z</updated>

		<summary type="html">&lt;p&gt;require( &amp;#039;strict&amp;#039; )&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- getting opening hours from Wikidata&lt;br /&gt;
&lt;br /&gt;
-- module variable and administration&lt;br /&gt;
local hr = {&lt;br /&gt;
	moduleInterface = {&lt;br /&gt;
		suite  = &amp;#039;Hours&amp;#039;,&lt;br /&gt;
		serial = &amp;#039;2022-10-22&amp;#039;,&lt;br /&gt;
		item   = 99600452&lt;br /&gt;
	},&lt;br /&gt;
	labelTable = nil&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- module import&lt;br /&gt;
-- require( &amp;#039;strict&amp;#039; )&lt;br /&gt;
local hi = require( &amp;#039;Module:Hours/i18n&amp;#039; )&lt;br /&gt;
local wu = require( &amp;#039;Module:Wikidata utilities&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
-- local variables&lt;br /&gt;
local categIds    = {}&lt;br /&gt;
local showOptions = {}&lt;br /&gt;
&lt;br /&gt;
local function isSet( s )&lt;br /&gt;
	return s and s ~= &amp;#039;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- insert a value into a table only if it is set&lt;br /&gt;
local function tableInsert( tab, value )&lt;br /&gt;
	if isSet( value ) then&lt;br /&gt;
		table.insert( tab, value )&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- value count for any variable&lt;br /&gt;
local function getCount( tab )&lt;br /&gt;
	return type( tab ) == &amp;#039;table&amp;#039; and #tab or 0&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getLabelFromTables( id )&lt;br /&gt;
	local label = hi.dateIds[ id ]&lt;br /&gt;
	if not label and hr.labelTable then&lt;br /&gt;
		label = hr.labelTable[ id ]&lt;br /&gt;
	end&lt;br /&gt;
	return label&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- getting normalized time hh:dd&lt;br /&gt;
local function getNormalizedTime( s )&lt;br /&gt;
	local count&lt;br /&gt;
	s, count = mw.ustring.gsub( s, hi.texts.timePattern, &amp;#039;%1:%2&amp;#039; )&lt;br /&gt;
	return ( count &amp;gt; 0 ) and s or nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function hr.formatTime( s )&lt;br /&gt;
	local t = getNormalizedTime( s )&lt;br /&gt;
	if not t then&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local formatStr = hi.texts.formatTime&lt;br /&gt;
	t = mw.text.split( t, &amp;#039;:&amp;#039;, true )&lt;br /&gt;
	if #t == 1 then&lt;br /&gt;
		t[ 2 ] = &amp;#039;00&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if hi.options.hour12 then&lt;br /&gt;
		local isAM = true&lt;br /&gt;
		local n = tonumber( t[ 1 ] )&lt;br /&gt;
		if n &amp;gt; 12 then&lt;br /&gt;
			isAM = false&lt;br /&gt;
			t[ 1 ] = &amp;#039;&amp;#039; .. ( n - 12 )&lt;br /&gt;
		end&lt;br /&gt;
		formatStr = isAM and hi.texts.formatAM or hi.texts.formatPM&lt;br /&gt;
	end&lt;br /&gt;
	s = mw.ustring.format( formatStr, mw.text.trim( t[ 1 ] ),&lt;br /&gt;
		mw.text.trim( t[ 2 ] ) )&lt;br /&gt;
	if hi.options.leadingZero then&lt;br /&gt;
		s = s:gsub( &amp;#039;^(%d):&amp;#039;, &amp;#039;0%1:&amp;#039; )&lt;br /&gt;
	else&lt;br /&gt;
		s = s:gsub( &amp;#039;^0(%d):&amp;#039;, &amp;#039;%1:&amp;#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if hi.options.removeZeros then&lt;br /&gt;
		s = s:gsub( &amp;#039;^(%d%d?):00&amp;#039;, &amp;#039;%1&amp;#039; )&lt;br /&gt;
	end&lt;br /&gt;
	return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- getting label for a qualifier id&lt;br /&gt;
-- to save computing time firstly the id will fetched from Hours/i18n table&lt;br /&gt;
-- if available, otherwise from Wikidata&lt;br /&gt;
local function getLabelFromId( id, wikilang, fallbackLang )&lt;br /&gt;
	if not isSet( id ) then&lt;br /&gt;
		return &amp;#039;&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- from table&lt;br /&gt;
	local label = getLabelFromTables( id )&lt;br /&gt;
&lt;br /&gt;
	-- from Wikidata&lt;br /&gt;
	if not label and mw.wikibase.isValidEntityId( id ) then&lt;br /&gt;
		label = wu.getLabel( id, wikilang )&lt;br /&gt;
		if not label and isSet( fallbackLang ) then&lt;br /&gt;
			label = wu.getLabel( id, fallbackLang )&lt;br /&gt;
			if label then&lt;br /&gt;
				categIds.fallbackLabel = &amp;#039;&amp;#039;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if label then&lt;br /&gt;
			categIds.labelFromWikidata = &amp;#039;&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- abbreviate labels&lt;br /&gt;
	if isSet( label ) then&lt;br /&gt;
		for i, abbr in ipairs( hi.abbr ) do&lt;br /&gt;
			label = mw.ustring.gsub( label, abbr.f, abbr.a )&lt;br /&gt;
		end&lt;br /&gt;
		label = mw.ustring.gsub( label, &amp;#039;​&amp;#039;, &amp;#039;&amp;#039; ) -- zero-width space&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- additional time formatting&lt;br /&gt;
	if isSet( label ) then&lt;br /&gt;
		if hi.months then&lt;br /&gt;
			for full, short in pairs( hi.months ) do&lt;br /&gt;
				label = mw.ustring.gsub( label, full, short )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		label = hr.formatTime( label )&lt;br /&gt;
	end&lt;br /&gt;
	return label or &amp;#039;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function abbreviateTimeStr( s, all, pattern, repl )&lt;br /&gt;
	if not isSet( s ) or not isSet( pattern ) or not repl then&lt;br /&gt;
        return s or &amp;#039;&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if all then&lt;br /&gt;
		s = mw.ustring.gsub( s, pattern, repl )&lt;br /&gt;
	else&lt;br /&gt;
		local matchPattern = mw.ustring.gsub( pattern, &amp;#039;%(%%d%)&amp;#039;, &amp;#039;&amp;#039; )&lt;br /&gt;
		local first, stop = mw.ustring.find( s, pattern )&lt;br /&gt;
		if first then&lt;br /&gt;
			local second = mw.ustring.find( s, pattern, stop + 1 )&lt;br /&gt;
			if second and mw.ustring.match( s, matchPattern ) ==&lt;br /&gt;
				mw.ustring.match( s, matchPattern, stop + 1 ) then&lt;br /&gt;
        		s = mw.ustring.gsub( s, pattern, repl, 1 )&lt;br /&gt;
        	end&lt;br /&gt;
    	end&lt;br /&gt;
    end&lt;br /&gt;
    return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- getting time period string&lt;br /&gt;
-- i:  position in from and to arrays&lt;br /&gt;
-- id: label for P3035 value&lt;br /&gt;
local function getTimePeriod( from, to, i, id )&lt;br /&gt;
	local result = &amp;#039;&amp;#039;&lt;br /&gt;
	if id and ( id == getLabelFromTables( hi.times.daily )&lt;br /&gt;
		or id == getLabelFromTables( hi.times.is24_7 ) )&lt;br /&gt;
		and from and to and from[ i ] == getLabelFromTables( hi.times.Jan1 ) and&lt;br /&gt;
		to[ i ] == getLabelFromTables( hi.times.Dec31 ) then&lt;br /&gt;
		return &amp;#039;&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if from and isSet( from[ i ] ) and to and isSet( to[ i ] ) then&lt;br /&gt;
		result = mw.ustring.format( hi.texts.fromTo, from[ i ], to[ i ] )&lt;br /&gt;
		if isSet( hi.texts.hourPattern ) then&lt;br /&gt;
			result = abbreviateTimeStr( result, hi.texts.hourReplAll,&lt;br /&gt;
				hi.texts.hourPattern, hi.texts.hourRepl )&lt;br /&gt;
		end&lt;br /&gt;
	elseif from and isSet( from[ i ] ) then&lt;br /&gt;
		result = mw.ustring.format( hi.texts.from, from[ i ] )&lt;br /&gt;
	elseif to and isSet( to[ i ] ) then&lt;br /&gt;
		result = mw.ustring.format( hi.texts.to, to[ i ] )&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- collecting all maintenance categories&lt;br /&gt;
function hr.getCategories( formatStr )&lt;br /&gt;
	local result = wu.getCategories( formatStr )&lt;br /&gt;
	for k, v in pairs( categIds ) do&lt;br /&gt;
		result = result .. ( hi.categories[ k ] or hi.categories.unknownError )&lt;br /&gt;
	end&lt;br /&gt;
	if showOptions.demo then&lt;br /&gt;
		-- remove category links&lt;br /&gt;
		result = result:gsub( &amp;#039;%[%[[^%[]*%]%]&amp;#039;, &amp;#039;&amp;#039; )&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- getting a string with listed days at which an establishment is closed&lt;br /&gt;
local function getClosed( arr )&lt;br /&gt;
	return ( arr and #arr &amp;gt; 0 ) and mw.ustring.format( hi.texts.closed or &amp;#039;%s&amp;#039;, &lt;br /&gt;
		table.concat( arr, hi.texts.separator ) ) or &amp;#039;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- converting day range from Mo, Tu, We to Mo–We, and so on&lt;br /&gt;
local function getRange( arr, minPos, maxPos )&lt;br /&gt;
	if maxPos &amp;gt; 0 and minPos &amp;gt; 0 and maxPos &amp;gt; minPos then&lt;br /&gt;
		arr[ minPos ] = mw.ustring.format( hi.texts.fromTo, arr[ minPos ],&lt;br /&gt;
			arr[ maxPos ] )&lt;br /&gt;
		for i = maxPos, minPos + 1, -1 do&lt;br /&gt;
			table.remove( arr, i )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- looking for day ranges like Mo, Tu, We and so on and converting them&lt;br /&gt;
local function convertDayRange( arr )&lt;br /&gt;
	local count = #arr&lt;br /&gt;
	local minPos = 0&lt;br /&gt;
	local maxPos = 0&lt;br /&gt;
	local value, valueMin&lt;br /&gt;
	while count &amp;gt; 0 do&lt;br /&gt;
		value = hi.weekdays[ arr[ count ] ]&lt;br /&gt;
		if not value then&lt;br /&gt;
			getRange( arr, minPos, maxPos )&lt;br /&gt;
			maxPos = 0&lt;br /&gt;
		elseif maxPos == 0 then&lt;br /&gt;
			maxPos = count&lt;br /&gt;
			valueMin = value&lt;br /&gt;
		elseif maxPos &amp;gt; 0 and value == valueMin - 1 then&lt;br /&gt;
			minPos = count&lt;br /&gt;
			valueMin = value&lt;br /&gt;
		else&lt;br /&gt;
			getRange( arr, minPos, maxPos )&lt;br /&gt;
			maxPos = 0&lt;br /&gt;
		end&lt;br /&gt;
		count = count - 1&lt;br /&gt;
	end&lt;br /&gt;
	getRange( arr, minPos, maxPos )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- concating non-empty strings&lt;br /&gt;
local function concatStrings( sep, str1, str2 )&lt;br /&gt;
	local tab = {}&lt;br /&gt;
	tableInsert( tab, str1 )&lt;br /&gt;
	tableInsert( tab, str2 )&lt;br /&gt;
	return table.concat( tab, sep )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- add comment if not yet exists&lt;br /&gt;
local function addComment( tab, value )&lt;br /&gt;
	if not isSet( value ) then&lt;br /&gt;
		return&lt;br /&gt;
	elseif #tab == 0 then&lt;br /&gt;
		table.insert( tab, value )&lt;br /&gt;
	else&lt;br /&gt;
		for i = 1, #tab, 1 do&lt;br /&gt;
			if tab[ i ] == value then&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
			if i == #tab then&lt;br /&gt;
				table.insert( tab, value )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- main function for usage in Lua modules&lt;br /&gt;
-- entity: entity id or entity table&lt;br /&gt;
-- wikilang: content language of the wiki&lt;br /&gt;
-- fallbackLang: optional additional language for fallback&lt;br /&gt;
-- formatStr: optional format string for property categories&lt;br /&gt;
-- show: table of show options (addCategories, msg, nomsg) or nil&lt;br /&gt;
-- lastedit: dat of last edit. If false no date will be fetched&lt;br /&gt;
-- labelTabel: additional table with Q-id label pairs&lt;br /&gt;
function hr.getHoursFromWikidata( entity, wikilang, fallbackLang, formatStr,&lt;br /&gt;
	show, lastEdit, labelTable )&lt;br /&gt;
&lt;br /&gt;
	-- collecting days at which an establishment is closed&lt;br /&gt;
	local closeDays = {}&lt;br /&gt;
	local closeDaysHelper = {}&lt;br /&gt;
	local function mergeDays( days )&lt;br /&gt;
		if not days or #days == 0 then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
		for i, day in ipairs( days ) do&lt;br /&gt;
			if not closeDaysHelper[ day ] then&lt;br /&gt;
				table.insert( closeDays, day )&lt;br /&gt;
				closeDaysHelper[ day ] = &amp;#039;&amp;#039;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local function clearDays()&lt;br /&gt;
		closeDays = {}&lt;br /&gt;
		closeDaysHelper = {}&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- adding additional properties if an additional Q-id table is given&lt;br /&gt;
	hr.labelTable = labelTable&lt;br /&gt;
&lt;br /&gt;
	-- preparing show options&lt;br /&gt;
	showOptions = show or {}&lt;br /&gt;
	showOptions.addCategories = hi.options.addCategories&lt;br /&gt;
	if showOptions.msg then&lt;br /&gt;
		showOptions.addCategories = true&lt;br /&gt;
	elseif showOptions.nomsg then&lt;br /&gt;
		showOptions.addCategories = false&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- format string for property categories&lt;br /&gt;
	if not isSet( formatStr ) then&lt;br /&gt;
		formatStr = hi.categories.properties&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- 1st step: getting statements for P3025: open days&lt;br /&gt;
	local statements = wu.getValuesWithQualifiers( entity, hi.wd.opened, nil,&lt;br /&gt;
		hi.wd.all, hi.wd.retrieved, nil, getLabelFromId, wikilang, fallbackLang )&lt;br /&gt;
	lastEdit = wu.getLastedit( lastEdit, statements )&lt;br /&gt;
&lt;br /&gt;
	-- converting statements to human-readable strings&lt;br /&gt;
	local result = {}&lt;br /&gt;
	local comments, s&lt;br /&gt;
	local is24_7 = getLabelFromTables( hi.times.is24_7 )&lt;br /&gt;
&lt;br /&gt;
	for i, statement in ipairs( statements ) do&lt;br /&gt;
		-- opening times&lt;br /&gt;
		local times = {}&lt;br /&gt;
		local count = math.max( getCount( statement[ hi.wd.hourOpen ] ),&lt;br /&gt;
			getCount( statement[ hi.wd.hourClosed ] ) )&lt;br /&gt;
		if count &amp;gt; 0 then&lt;br /&gt;
			for j = 1, count, 1 do&lt;br /&gt;
				s = getTimePeriod( statement[ hi.wd.hourOpen ],&lt;br /&gt;
					statement[ hi.wd.hourClosed ], j )&lt;br /&gt;
				if isSet( s ) then&lt;br /&gt;
					table.insert( times, s )&lt;br /&gt;
				elseif statement.value ~= is24_7 then&lt;br /&gt;
					categIds.withoutTime = &amp;#039;&amp;#039;&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		elseif statement.value ~= is24_7 then&lt;br /&gt;
			categIds.withoutTime = &amp;#039;&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		s = table.concat( times, hi.texts.separator )&lt;br /&gt;
&lt;br /&gt;
		-- comments&lt;br /&gt;
		comments = {}&lt;br /&gt;
		count = math.max( getCount( statement[ hi.wd.dayOpen ] ),&lt;br /&gt;
			getCount( statement[ hi.wd.dayClosed ] ) )&lt;br /&gt;
		for j = 1, count, 1 do&lt;br /&gt;
			addComment( comments,&lt;br /&gt;
				getTimePeriod( statement[ hi.wd.dayOpen ],&lt;br /&gt;
					statement[ hi.wd.dayClosed ], j, statement.value ) )&lt;br /&gt;
		end&lt;br /&gt;
		for j, key in ipairs( hi.wd.comments ) do&lt;br /&gt;
			if statement[ key ] then&lt;br /&gt;
				addComment( comments, table.concat( statement[ key ],&lt;br /&gt;
					hi.texts.separator ) )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		-- concating times and comments&lt;br /&gt;
		times = {}&lt;br /&gt;
		tableInsert( times, s )&lt;br /&gt;
		s = table.concat( comments, hi.texts.separator )&lt;br /&gt;
		if isSet( s ) then&lt;br /&gt;
			table.insert( times, mw.ustring.format( hi.texts.comment, s ) )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		local item = {}&lt;br /&gt;
		tableInsert( item, table.concat( times, hi.texts.joiner ) )&lt;br /&gt;
&lt;br /&gt;
		-- close statements (P3026) as qualifiers for open days property (P3025)&lt;br /&gt;
		mergeDays( statement[ hi.wd.closed ] )&lt;br /&gt;
		if not hi.options.clusterClosed and ( i == #statements or&lt;br /&gt;
			statements[ i ].value ~= statements[ i + 1 ].value ) then&lt;br /&gt;
			convertDayRange( closeDays )&lt;br /&gt;
			tableInsert( item, getClosed( closeDays ) )&lt;br /&gt;
			clearDays()&lt;br /&gt;
		end&lt;br /&gt;
		s = table.concat( item, hi.texts.separator )&lt;br /&gt;
	&lt;br /&gt;
		-- copying each statement to result table&lt;br /&gt;
		if statement.sort2 == 1 then&lt;br /&gt;
			tableInsert( result, { value = { statement.value }, times = s } )&lt;br /&gt;
		elseif s ~= &amp;#039;&amp;#039; then&lt;br /&gt;
			result[ #result ].times = concatStrings( hi.texts.separator,&lt;br /&gt;
				result[ #result ].times, s )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- checking for duplicates&lt;br /&gt;
	for i = #result, 2, -1 do&lt;br /&gt;
		if result[ i ].times == result[ i - 1 ].times then&lt;br /&gt;
			for j, value in ipairs( result[ i ].value ) do&lt;br /&gt;
				table.insert( result[ i - 1 ].value, value )&lt;br /&gt;
			end&lt;br /&gt;
			table.remove( result, i )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- converting day range&lt;br /&gt;
	for i = 1, #result, 1 do&lt;br /&gt;
		local arr = result[ i ].value&lt;br /&gt;
		convertDayRange( arr )&lt;br /&gt;
		result[ i ] = concatStrings( hi.texts.joiner,&lt;br /&gt;
			table.concat( arr, hi.texts.separator ), result[ i ].times )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- 2nd step: getting separated close statements (P3026)&lt;br /&gt;
	local statements = wu.getValuesWithQualifiers( entity, hi.wd.closed, nil,&lt;br /&gt;
		hi.wd.commentsForClosed, hi.wd.retrieved, nil, getLabelFromId, wikilang,&lt;br /&gt;
		fallbackLang )&lt;br /&gt;
	if #statements &amp;gt; 0 then&lt;br /&gt;
		lastEdit = wu.getLastedit( lastEdit, statements )&lt;br /&gt;
&lt;br /&gt;
		-- getting closed values&lt;br /&gt;
		local closed = {}	&lt;br /&gt;
		for i, statement in ipairs( statements ) do&lt;br /&gt;
			local closedDate = {}&lt;br /&gt;
			table.insert( closedDate, statement.value )&lt;br /&gt;
&lt;br /&gt;
			-- getting comments&lt;br /&gt;
			comments = {}&lt;br /&gt;
			for j, key in ipairs( hi.wd.commentsForClosed ) do&lt;br /&gt;
				if statement[ key ] then&lt;br /&gt;
					addComment( comments, table.concat( statement[ key ],&lt;br /&gt;
						hi.texts.separator ) )&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			s = table.concat( comments, hi.texts.separator )&lt;br /&gt;
			if isSet( s ) then&lt;br /&gt;
				table.insert( closedDate, mw.ustring.format( hi.texts.comment, s ) )&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			table.insert( closed, table.concat( closedDate, hi.texts.joiner ) )&lt;br /&gt;
		end&lt;br /&gt;
		mergeDays( closed )&lt;br /&gt;
	end&lt;br /&gt;
	convertDayRange( closeDays )&lt;br /&gt;
	tableInsert( result, getClosed( closeDays ) )&lt;br /&gt;
&lt;br /&gt;
	-- 3rd step: adding additional statements&lt;br /&gt;
	local statements = wu.getValuesWithQualifiers( entity, hi.wd.stateOfUse,&lt;br /&gt;
		nil, {}, hi.wd.retrieved, nil, getLabelFromId, wikilang, fallbackLang )&lt;br /&gt;
	if #statements &amp;gt; 0 then&lt;br /&gt;
		lastEdit = wu.getLastedit( lastEdit, statements )&lt;br /&gt;
		for i, statement in ipairs( statements ) do&lt;br /&gt;
			tableInsert( result, statement.value )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- merging all statements&lt;br /&gt;
	local result = table.concat( result, hi.texts.delimiter )&lt;br /&gt;
&lt;br /&gt;
	-- adding maintenance categories&lt;br /&gt;
	if result ~= &amp;#039;&amp;#039; then&lt;br /&gt;
		categIds.fromWikidata = &amp;#039;&amp;#039;&lt;br /&gt;
		if showOptions.addCategories then&lt;br /&gt;
			result = result .. hr.getCategories( formatStr )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result, lastEdit&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- invoke helper functions&lt;br /&gt;
-- splitting show parameters&lt;br /&gt;
local function splitAndCheck( s )&lt;br /&gt;
	local arr = {}&lt;br /&gt;
	local err = {}&lt;br /&gt;
	if isSet( s ) then&lt;br /&gt;
		for i, v in ipairs( mw.text.split( s, &amp;#039;,&amp;#039;, true ) ) do&lt;br /&gt;
			v = mw.text.trim( v )&lt;br /&gt;
			if not hi.show[ v ] then&lt;br /&gt;
				table.insert( err, v )&lt;br /&gt;
			else&lt;br /&gt;
				arr[ v ] = &amp;#039;&amp;#039;&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return arr, err&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- check if pareameters are valid&lt;br /&gt;
local function checkParameters( args )&lt;br /&gt;
	local err = {}&lt;br /&gt;
	if not args and type( args ) ~= &amp;#039;table&amp;#039; then&lt;br /&gt;
		return err&lt;br /&gt;
	end&lt;br /&gt;
	for k, v in pairs( args ) do&lt;br /&gt;
		if not hi.params[ k ] then&lt;br /&gt;
			table.insert( err, k )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return err&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- formating and concating error strings&lt;br /&gt;
local function getErrorStr( arr, formatStr )&lt;br /&gt;
	return #arr == 0 and &amp;#039;&amp;#039; or&lt;br /&gt;
		mw.ustring.format( formatStr, table.concat( arr, &amp;#039;, &amp;#039; ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- main function for template #invoke calls&lt;br /&gt;
-- id: Q id of an establishment&lt;br /&gt;
-- format: output format like &amp;#039;opened at %s&amp;#039;&lt;br /&gt;
-- fallback: fallback language if labels are not available in content language&lt;br /&gt;
function hr.getHours( frame )&lt;br /&gt;
    local args = frame.args&lt;br /&gt;
    args.id = mw.text.trim( args.id or &amp;#039;&amp;#039; )&lt;br /&gt;
    if not isSet( args.id ) or not mw.wikibase.isValidEntityId( args.id ) then&lt;br /&gt;
        return hi.categories.invalidId&lt;br /&gt;
    end&lt;br /&gt;
    if not isSet( args.format ) then&lt;br /&gt;
    	args.format = hi.texts.format&lt;br /&gt;
    else&lt;br /&gt;
	    local s, count = args.format:gsub( &amp;#039;%%s&amp;#039;, &amp;#039;%%s&amp;#039; )&lt;br /&gt;
    	if count ~= 1 then&lt;br /&gt;
        	args.format = hi.texts.format&lt;br /&gt;
    	end&lt;br /&gt;
    end&lt;br /&gt;
    args.fallback = args.fallback or &amp;#039;&amp;#039;&lt;br /&gt;
    local wikilang = mw.getContentLanguage():getCode()&lt;br /&gt;
&lt;br /&gt;
	local paramErr = checkParameters( args )&lt;br /&gt;
	local show, showErr = splitAndCheck( args.show )&lt;br /&gt;
&lt;br /&gt;
    local result, lastEdit = hr.getHoursFromWikidata( args.id, wikilang,&lt;br /&gt;
    	args.fallback, &amp;#039;&amp;#039;, show, false, nil )&lt;br /&gt;
    if result ~= &amp;#039;&amp;#039; then&lt;br /&gt;
    	result = mw.ustring.format( args.format, result )&lt;br /&gt;
    end&lt;br /&gt;
    return result .. getErrorStr( paramErr, hi.categories.unknownParams )&lt;br /&gt;
    	.. getErrorStr( showErr, hi.categories.unknownShowOptions )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return hr&lt;/div&gt;</summary>
		<author><name>wikivoyage&gt;RolandUnger</name></author>
	</entry>
</feed>