Dátumszűrés[mi ez?] • [dokumentáció: mutat, szerkeszt] • [tesztek: sikeres: 2, sikertelen: 0, kihagyva: 0 (részletek)]

Használata

szerkesztés
Kód Eredménye
local ds = require 'Modul:Dátumszűrés'
ds.honapnevesdate(select(2, ds.datumszuro('1988 ápr 11')))
1988. április 11.
local ds = require 'Modul:Dátumszűrés'
ds.honapnevesdate(select(2, ds.datumszuro('July 1st, 2000')))
2000. július 1.

Lásd még: Tesztek, Modul:Dátumszűrés/tests

-- A MODUL FÜGGVÉNYEIT ÉS ADATAIT CSAK require('Modul:Dátumszűrés') MÓDON TUDJUK ELÉRNI.
-- A CitWeb és családja számára készült el.

require('strict')
local getArgs = require('Modul:Arguments').getArgs

-- a magyar dátumhoz kell
local honapok = { 'január', 'február', 'március', 'április', 'május', 'június',
	'július', 'augusztus', 'szeptember', 'október', 'november', 'december'
}

-- ellenőrizzük az egyes hónapok hosszát
local honaphossz = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

-- pop a nyomkövetés céljait szolgálja
local ou = ''
local function pop(...) -- idézőjeles rész és bővítmények az ou számára
--[[ memóriatúllépést okoz, csak teszteléshez
	local list = {...}
	for _, var in pairs(list) do
		ou = ou .. tostring(var) .. '\n '
		mw.log(ou)
	end
]]
end

-- a magyar helyesírás szerinti rövidített hónapnevek a honapnevesdate() kimenetének
-- előállításához

-- az ISO 8604 szabvány szerinti dátumban a hónap helyére lépő stringet szolgáltatja
local honapsorszamekezetnelkul = {
	['jan'] = '01', -- january, Januar
	['feb'] = '02', -- february, Februar, février
	['mar'] = '03', -- mars, März, mars
	['apr'] = '04', -- april, avril első betű a, második v APRL AVRL
	['maj'] = '05', -- may mai mai az első betű m, a harmadik nem r MAY
	['jun'] = '06', -- june, juin az első kettő ju de a harmadik i JUN
	['jul'] = '07', -- july, juli, juillet viszont itt is i, VEGYÜK KI AZ I-T A NÉVBŐL: JUL
	['aug'] = '08', -- august, aout első betű a, második o
	['sze'] = '09', -- sept
	['okt'] = '10',
	['nov'] = '11',
	['dec'] = '12'
}

-- a római számmal megadott hónap decimális megfelelője
local decimal = {
	['I'] = 1,
	['II'] = 2,
	['III'] = 3,
	['IV'] = 4,
	['V'] = 5,
	['VI'] = 6,
	['VII'] = 7,
	['VIII'] = 8,
	['IX'] = 9,
	['X'] = 10,
	['XI'] = 11,
	['XII'] = 12
}

local hibavan = false





-- kell a dátum ellenőrzéséhez
-- a numerikus dátumokat kezeli le és ISO 8604 szabvány szerinti dátumot csinál a bemeneti esetleg helytelenül megadott dátumból

--[[
DÁTUMSZŰRŐ:
Kiszűri a bemenetén kapott dátumokból
a) a csupa számból álló ISO 8604 dátumokat
b) a római számmal megadott magyar dátumokat
c) a magyar vagy idegen hónapneveket tartalmazó dátumokat
és ezekből mind helyesen formázott ISO 8604 dátumokat csinál
--]]

local function error(about) -- hibajelzést szolgál
	-- Enclose errorMsg with <span>
	-- Precondition:
	--     about -- string
	hibavan = true
	local r = about
	if type(about) == 'string' then
		if #about == 0 then
			r = 'Lua-hiba'
		end
	else
	r = tostring(about)
	end
	return '<span class="error">' .. r .. '</span>, '
end -- error()

local function isRoman(v)
	if type(v) ~= 'string' then
		-- A római számok stringek
		return false
	end
	if v:find('[^IVXLCDM]') then
		return false
	end
end

--[[ month_to_hu(m)
segéd-funkció, mely az idegen hónapneveket helyettesíti azékezet nélküli, három karakteres rövidített
magyar hónapnevekre (a rövidítést nem jelzi ponntal)
Ennek alapján beküzdi a kétjegyű hónap-sorszámot az ISO 8604 szabványnak megfelelő alakban
--]]
local function month_to_hu(m)
	--[[
		Spanyol: enero febrero marzo abril mayo junio julio ago septiembre v. setiembre octubre noviembre diziembre
		Portugál: janeiro fevereiro marco abril maio junho julho agosto setembro outubro novembro dezembro
		Olasz: gennaio febbraio marzo aprile maggio giugno luglio agosto settembre ottobre novemre dicembre
	--]]
	local alfa, eb, ub, e2b
	if not m then
		return
	end
	m = string.gsub(m, ' ', '') -- cseréljük fel a szóközöket üressel
	m = string.gsub(m, 'ä', 'a') -- März, mars problem ôû
	m = string.gsub(m, 'û', 'u')
	m = string.lower(m) -- minden kisbetűs
	alfa = string.match(m, '[a-z%-]+') -- kötőjel problémás
	if alfa then -- vannak egyáltalán betűk
		pop('1- alfa=', alfa)
		m = string.sub(m, 1, 3) --három betünk van
		eb = string.sub(m, 1, 1)
		if eb == 'm' then
			ub = string.sub(m, -1, -1)
			if     ub == 'i' then m = 'maj'
			elseif ub == 'r' then m = 'mar'
			elseif ub == 'y' then m = 'maj'
			elseif ub == 'g' then m = 'maj' --maggio
			end
		elseif eb == 'e' then
			m = 'jan' --spanyol
		elseif eb == 'g' then
			e2b = string.sub(m, 1, 2)
			if e2b == 'ge' then
				m = 'jan'
			elseif e2b == 'gi' then
				m = 'jun' --- olasz
			end
		elseif eb == 'j' then
			if string.sub(m, 2, 2) == 'a' then
				m = 'jan'
			elseif string.sub(m, 3, 3) == 'n' then
				m = 'jun'
			elseif string.sub(m, 3, 3) == 'i' then
				m = 'jul'
			end
		elseif eb == 'a' then
			if m:find('^a[pvb]') then
				m = 'apr'
			elseif m:find('^a[ugo]') then
				m = 'aug'
			end
		elseif eb == 'f' then m = 'feb'
		elseif eb == 'l' then m = 'jul' --olasz
		elseif eb == 's' then m = 'sze'
		elseif eb == 'o' then m = 'okt'
		elseif eb == 'n' then m = 'nov'
		elseif eb == 'd' then m = 'dec'
		else
			return false
		end
	else
		return false
	end
	return	m
end

local function szokoev(ev)
	if ev == nil then
		return false
	end
	local e = tonumber(ev)
	if e then -- is numeric?
		if e % 400 == 0 then return true end
		if e % 100 == 0 then return false end
		if e % 4 == 0 then return true end
	end
	return false
end

--[[ en_to_hu(de)
	Angol vagy amerikai angol dátumokból, illetve német, francia, olasz, spanyol
	 és portugál dátumokból csinál ISO 8604 szabvány szerinti dátumot. Esetleg
	 bővíthető ez a lista, ha nem vezet kollízióra az idegen neveket értelmező
	 en_to_hu funkcióban. Hibás dátum esetén false értékkel tér vissza.
--]]
local function en_to_hu(de)
	pop('en_to_hu indul')
	--Az angol dátumokat jó lenne felismernie: "Dec. 10, 2013". string.lower(s)
	local ev, ho, nap, maradek
	if type(de) ~= 'string' then
		return false
	end
	de = string.gsub(de, ' ', '') -- cseréljük fel a szóközöket üressel
	de = string.gsub(de, '[%.%-]', '/')-- cseréljük fel a pontot és kötőjelet perjellel dec/10/2013
	--éôûäde = string.gsub(de, 'é', 'e')--éôûäF
	de = string.lower(de) -- minden kisbetűs

	ev = string.match(de, '%d%d%d%d?')-- keress a dátumban az évet 2013
	if ev then
		maradek = string.gsub(de, ev, '')
	else
		return false
	end
	if maradek then
		pop('en maradek?', maradek)
		-- számmal indul mert little endian
		maradek = string.gsub(maradek, '/', '') -- már nincsenek perjelek dec10, vagy pl dec
		local i, j
		i, j = string.match(maradek, '()%d%d?()')
		pop('nap indexei a maradékban=', i, j)
		if j then
			nap = string.sub(maradek, i, j-1)
		end
		pop('nap ?= ', nap)

		if nap then
			ho = string.gsub(maradek, nap, '')
		else
			ho = maradek
		end						-- azaz dec10 esetén marad dec, dec esetén pedig ő a hónap
	end

	de = ev
	ho = honapsorszamekezetnelkul[month_to_hu(ho)]
	if ho then
		de = de .. '-' .. ho
	end
	if nap then
		de = de .. '-' .. nap
	end -- összeraktuk a dátumot
	pop('USA&en átalakult?', de)
	local honum = tonumber(ho)
	pop('honum', honum)
	if honum == nil or 1 > honum or honum > 12 then
		return false -- hónap sorszáma hibás
	end
	pop('nap=', nap)
	pop('nap típusa: ', type(nap))
	if nap then
		local napnum = tonumber(nap)
		pop('napnum', napnum)
		if napnum ~= nil and 1 <= napnum and napnum <= 31 then
			pop('napnum jó?g', napnum)
			if szokoev(ev) then
				honaphossz[2] = 29
			else
				honaphossz[2] = 28
			end
			if honaphossz[honum] < napnum then
				return false
			end -- nap sorszáma hibás
		else
			return false
		end -- nap sorszáma hibás
	end
	return de
end

local function ekezet_le(s)
	s = string.gsub(s, 'á', 'a')
	s = string.gsub(s, 'é', 'e')
	s = string.gsub(s, 'í', 'i')
	s = string.gsub(s, 'ó', 'o')
	s = string.gsub(s, 'ő', 'ö')
	s = string.gsub(s, 'ú', 'u')
	s = string.gsub(s, 'ű', 'ö')
	s = string.gsub(s, 'ä', 'a')
	s = string.gsub(s, 'ô', 'o')
	s = string.gsub(s, 'û', 'u')
	return s
end


local function numdate(de)
	local ev, ho, nap, i, j, maradek
	local de, perek = string.gsub(de, '%-', '/')
	pop('numdate de perekkel = ', de, tostring(perek))
	if perek == 2 then
		i, j = string.find(de, '/')
		pop('numdate_2peres, benne hol a perjel = ', i, j)
		ev = string.sub(de, 1, j-1)
		maradek = string.sub(de, j+1, -1)
		pop('numdate_2peres: év, maradek = ' .. ev .. ', ' .. maradek)
		i, j = string.find(maradek, '/')
		pop('numdate_2peres i,j a hóhoz és naphoz = ', i, j)
		ho = string.sub(maradek, 1, j-1)
		nap = string.sub(maradek, j+1, -1)
		pop('2peres év, maradekban ho, nap = ', ho, nap)
	elseif perek == 1 then -- van év és hó
		i, j = string.find(de, '/')
		pop('numdate_1peres, benne hol a perjel = ', i, j)
		ev = string.sub(de, 1, j-1)
		ho = string.sub(de, j+1, -1)
		pop('numdate_1peres: év, hó = ', ev, ho)
	else
		ev = de
	end
	if #ev < 3 then
		return false
	end
	pop('év hossza=', tostring(#ev))
	if ho then
		local honum = tonumber(ho)
		pop('ho számmal=', tostring(honum))
		if honum then
			if 1 > honum or honum > 12 then
				-- hónap sorszáma hibás
				return false
			end

			if nap then
				local napnum = tonumber(nap)
				pop('nap számmal=', tostring(napnum))
				if not (napnum and 1 <= napnum and napnum <= 31) then
					return false
				end
				if szokoev(ev) then
					honaphossz[2] = 29
				else
					honaphossz[2] = 28
				end
				if honaphossz[honum] < napnum then
					pop('túl a hónaphatáron a nap')
					return false -- nap sorszáma hibás
				else
					pop('ellenőrzött év, hó, nap', ev, ho, nap)
				end
			end
		end
	end
	de = ev
	if ho and ho ~= '' then
		de = de .. '-' .. ho
	end
	if nap then
		de = de .. '-' .. nap
	end
	pop('numdate átadja:', de)
	return de
end



local function hudate(de)
	pop('hudate indul')
	local i, j, ev, ho, nap, maradek
	pop(de)
	ev = string.match(de, '^%d%d%d%d?') -- ééé v. éééé levágva ev-be
	if not ev then
		return false
	end
	pop('ev=', ev)
	local hostring = string.match(de, '%a+')
	if hostring then
		ho = string.sub(hostring, 1, 3)
	end

	pop('ho=', ho)
	if ho then
		i, j = string.find(de, ho)
		maradek = string.gsub(string.sub(de, j+1, -1), '%p', '')
		nap = string.match(maradek, '%d%d?')
		pop('nap=', nap)
	end
	if isRoman(ho) then
		ho = decimal[ho]
		if ho then
			-- A római számból decimálist csinál a tábla, ebből ismét string kell,
			-- hogy az if utasítás végén mindenképpen string hónapunk legyen
			ho = tostring(ho)
		else
			return false
		end
		pop('ho rómaiból = ', ho)
	else
		ho = honapsorszamekezetnelkul[ho]
	end
	if ho then
		local honum = tonumber(ho)
		pop('honum=', tostring(honum))
		if honum then
			if 1 > honum or honum > 12 then
				-- A hónap sorszáma hibás
				return false
			end

			if nap then
				local napnum = tonumber(nap)
				pop('napnum=', tostring(napnum))
				if not (napnum and 1 <= napnum and napnum <= 31) then
					return false
				end
				if szokoev(ev) then
					honaphossz[2] = 29
				else
					honaphossz[2] = 28
				end
				if honaphossz[honum] < napnum then
					pop('fals nap')
					return false -- nap sorszáma hibás
				else
					pop('másodszor', ev, ho, nap)
				end
			end
		end
	end
	if ho~= nil and #ho < 2 then
		ho = '0' .. ho
	end
	de = ev
	if ho then
		de = de .. '-' .. ho
	end
	if nap then
		de = de .. '-' .. nap
	end
	return de
end


--[[ datumszuro(de)
	megszűri a numerikus éééé-hh-nn, illetve a Dec. 10, 2001, 10 january 2001, 2001. december 10 formákat,
	leellenőrzi a dátumot (hónaphossz, létező hónap sorszám)
	és valamennyiből az ISO 8604 szabvány szerinti dátumot csinál
--]]
local function datumszuro(de)
	local log, cserelt
	if not de then
		return ou, false
	end
	-- Example: 2012-03-14T15:31:00
	if de:find('%d%d%d%d%-%d%d%-%d%d') == 1 and (de:len() == 10 or de:sub(11, 11) == 'T') then
		local ho, nap = de:match('%d%d%d%d%-(%d%d)%-(%d%d)')
		ho = tonumber(ho)
		nap = tonumber(nap)
		if not honaphossz[ho] or nap < 1 or nap > honaphossz[ho] then
			return ou, false
		end
		return ou, de:sub(1, 10)
	end
	-- Example: 17.02.1934.
	if de:match('^%d%d?%.%s*%d%d?%.%s*%d%d%d%d%.?$') then
		local nap, ho, ev = de:match('(%d%d?)%.%s*(%d%d?)%.%s*(%d%d%d%d)%.?')
		ho = tonumber(ho)
		nap = tonumber(nap)
		if not honaphossz[ho] or nap < 1 or nap > honaphossz[ho] then
			return ou, false
		end
		return ou, ('%s-%02d-%02d'):format(ev, ho, nap)
	end
	de, cserelt = string.gsub(de, '%.', '-')
	if cserelt == 2 then
		de = string.gsub(de, '%-*$', '')
	end -- ha a végén van kötőjel, lecsipjük
	pop('datumszurodatuma paramétere= ', de)
	de = ekezet_le(de)
	pop('ékezetek nélküli dátum=', de)
	de = string.gsub(de, '%s', '')
	local i, j = string.match(de, '()%d%d%d%d?()')
	if not j then
		return ou, false -- mert nincs év a dátumban
	else
		-- ha j == 5, akkor a dátum elején áll az év, magyar a dátum vagy ISO
		pop(i, j, string.sub(de, i, j-1))
	end
	if not de or type(de)~= 'string' then
		return ou, false
	end
	local d2 = string.gsub(de, '[%p%-]', '') -- punctuation, kötjel is üres lesz
	pop('d2 van benne kötjel?', d2)
	d2 = tonumber(d2)
	pop('d2 mint szám', d2)
	if d2 then
		--[[ a dátum számjegyes
		  adB1) keresünk %d%d%d%d? mintával négy- vagy háromjegyű decimálist a dátumban
		      ha van, megnézzük, hogy hol van ő a dátreturn 1, false endumban,
		      ha elől akkor tényleg magyar a dátum (átadjuk a kezelőjének: ennek nagy része már megvan az datumoutput-ban)
		      különben ad B2) höz
		--]]
		log = numdate(de)
		if log == false then
			-- hibás a dátum
			return ou, false
		end
	else
		-- betűk is vannak d2-ben
		local i, j = string.match(de, '^()%d%d%d%d?()')
		if j == 5 then
			log = hudate(de)-- mert magyar a dátum
			pop('hudate utáni dátum= ', log)-- meghívjuk a magyar dátum lekezelését log vagy false, vagy a magyar dátum
		else
			log = en_to_hu(de)
			pop('en_to_hu utáni dátum= ', log)
		end
	end

	if log == false then
		-- hibás a dátum
		return ou, false
	end

	pop('dátum a dátumszűrés végén = ', log)
	return ou, log -- azaz a dátum
end

local function honapnevesdate(isodate)
	local ev, ho, nap, i, j, maradek, de
	if not isodate then
		return
	end
	isodate = string.gsub(isodate, '%s+', '')
	i, j = string.find(isodate, '-')
	if i then
		ev, maradek = string.match(isodate, '(%d+)%s*%-%s*([%d%p%-]+)') --, ho, nap --%-%s*(%d+)%s*%s*(%d+)%s"
		pop('isodate ev,maradek=', ev, maradek)
		i, j = string.find(maradek, '-')
		if i then
			ho, nap = string.match(maradek, '(%d+)%s*%-%s*([%d%p%-]+)')
			pop('isodate ho, nap = ', tostring(ho), nap)
		else
			ho = maradek
		end
		ho = honapok[tonumber(ho)]
	else
		ev = isodate
	end
	de = ev
	if ho then
		de = de .. '. ' .. ho
	end
	if nap then
		de = de .. ' ' .. tonumber(nap) .. '.'
	end
	return de
end

-- csak a dátumszűrés és a honapnevesdate publikus a modulból
local p = {
	datumszuro = datumszuro,
	honapnevesdate = honapnevesdate
}

function p.toIsoDate(frame)
	local args = getArgs(frame)
	if not args[1] then
		return nil
	end
	local _, isoDate = datumszuro(args[1])
	if not isoDate then
		return args[1]
	end
	return isoDate
end

return p