Module:Kalender
Module voor kalenderberekeningen.
Functies:
- zijbalk_jaar: voor {{Zijbalk jaar}}
Maakt gebruik van:
- Bestand:Crystal Clear mimetype vcalendar.png
- Bestand:Calendar-nl.svg
- Bestand:Nuvola apps kuser.svg
- Bestand:Gnome-globe.svg
- Sjabloon:Infobox/breedte (=270)
- Sjabloon:Navigatie/titelbalkkleur (= var(--navigatie-titelbalkkleur,#ddeef8))
-- year numbers use ISO 8601 numbering
local p = {}
local BC = " v.Chr."
local AD = ""
local BC_LABEL = " v.C." -- only used for centuries
local AD_LABEL = " n.C." -- only used for centuries
local SEP = " · "
local INFOBOX_WIDTH = 'width:' .. mw.getCurrentFrame():expandTemplate{title = 'Infobox/breedte', args = {}} .. 'px;'
local TITLEBARCOLOR = 'background-color:' .. mw.getCurrentFrame():expandTemplate{title = 'Navigatie/titelbalkkleur', args = {}} .. '; color:inherit;'
-- {label, linkPrefix}
-- iedereen wordt uitgenodigd dit lijstje uit te breiden!
local themesTab = {
{"Lijst van landen", "Lijst van landen in"},
{"Lijst van staatshoofden en regeringsleiders", "Lijst van staatshoofden en regeringsleiders in"},
{"Lijst van regeringsleiders van afhankelijke territoria", "Lijst van regeringsleiders van afhankelijke territoria in"},
{"Geboren", "Lijst van personen geboren in"},
{"Overleden", "Lijst van personen overleden in"},
{"Machthebbers", "Machthebbers in"},
{"Aardbevingen", "Lijst van aardbevingen in"},
{"Atlantisch orkaanseizoen"},
{"Orkaanseizoen van de Grote Oceaan"},
{"Tyfoonseizoen van de Grote Oceaan"},
{"Wetenschap", "Wetenschap in"},
{"Auto's", "Europese auto in"}, --hierop staat navigatie naar andere werelddelen
{"Luchtvaart", "Luchtvaart in"},
{"Film", "Film in"},
{"Muziek", "Muziek in"},
{"Sport", "Sport in"},
{"Sportkalender"},
{"Sport (categorie)", ":Categorie:Sport in"},
}
-- lijst van overgangskalenders
-- [jaartal] = {gebiedsnaam 1, gebiedsnaam 2, enz.}
-- gebiedsnamen moeten overeenkomen met wat tussen eventuele haakjes staat in de artikeltitel
local transitionTab = {
[1582] = {"Zuid-Europa", "Frankrijk", "Brabant, Zeeland", "Zuidelijke Nederlanden"},
[1583] = {"Holland", "Groningen", "Augsburg", "Trier", "Oostenrijk west", "Gulik-Berg", "Keulen, Aken", "Würzburg", "Mainz", "Münster, Kleef, Baden", "Oostenrijk oost"},
[1584] = {"Bohemen, Moravië", "katholiek Zwitserland", "Lausitz, Silezië", "Westfalen"},
[1585] = {"Paderborn"},
[1587] = {"Hongarije"},
[1590] = {"Transsylvanië"},
[1594] = {"Groningen"},
[1610] = {"Pruisen"},
[1631] = {"Hildesheim"},
[1682] = {"Elzas"},
[1700] = {"Duitsland, Denemarken, Noorwegen", "Gelderland", "Utrecht, Overijssel"},
[1701] = {"Friesland, Groningen, protestants Zwitserland", "Drenthe"},
[1710] = {"vasteland van Nova Scotia"},
[1712] = {"Zweden"},
[1752] = {"Britse Rijk"},
[1753] = {"Zweden"},
[1800] = {"Litouwen"},
[1867] = {"Alaska"},
[1912] = {"Albanië"},
[1915] = {"Litouwen"},
[1916] = {"Bulgarije"},
[1918] = {"Estland, Rusland"},
[1919] = {"Koninkrijk der Serven, Kroaten en Slovenen", "Roemenië"},
[1923] = {"Griekenland"}
}
-- local functions
local function link(title, label)
if not label then
return '[[' .. title .. ']]'
else
return '[[' .. title .. '|' .. label .. ']]'
end
end
local function epoch(year)
if year > 0 then
return AD
else
return BC
end
end
local function yearInEpoch(year)
if year <= 0 then
year = -year + 1 -- 0 becomes 1 [BC]
end
return year
end
local function centuryInEpoch(year)
return math.floor((yearInEpoch(year) - 1) / 100) + 1
end
local function decade(year)
return math.floor(yearInEpoch(year) / 10)
end
-- e.g. "22 v.Chr."
local function yearString(year)
return yearInEpoch(year) .. epoch(year)
end
-- e.g. "[[22 v.Chr.]]"
local function yearLink(year, label)
local y = yearInEpoch(year)
if not label and y ~= 1 then
label = y
end
if year <= -999 then
return label
else
return link(y .. epoch(year), label)
end
end
-- e.g. "29-20 v.Chr."
local function decadeString(year)
local decade = decade(year)
local epoch = epoch(year)
local r
if epoch == BC then
if decade == 0 then
r = "9-1" .. epoch
else
r = decade .. "9-" .. decade .. "0" .. epoch
end
else
if decade == 0 then
r = "1-9" .. epoch
else
r = decade .. "0-" .. decade .. "9" .. epoch
end
end
return r
end
-- e.g. "[[29-20 v.Chr.|29-20]]"
local function decadeLink(year)
local decade = decade(year)
local epoch = epoch(year)
local r
if epoch == BC then
if decade == 0 then
r = link("9-1" .. epoch)
else
r = decade .. "9-" .. decade .. "0"
r = link(r .. epoch, r)
end
else
if decade == 0 then
r = link("1-9" .. epoch)
else
r = decade .. "0-" .. decade .. "9"
r = link(r .. epoch, r)
end
end
return r
end
-- e.g. "1e eeuw v.Chr."
local function centuryString(year)
return centuryInEpoch(year) .. "e eeuw" .. epoch(year)
end
-- e.g. "[[1e eeuw v.Chr.|1e eeuw]]"
local function centuryLink(year, epochLabel)
local prefix = centuryInEpoch(year) .. "e eeuw"
local title = prefix .. epoch(year)
local label
if epochLabel then
label = prefix .. epochLabel
end
return link(title, label)
end
local function bc(year)
return -year + 1
end
-- convert text to ISO year number
local function yearNumber(yearStr)
local i = mw.ustring.find(yearStr, BC, 1, true)
local r
if i then
r = bc(mw.ustring.sub(yearStr, 1, i))
else
r = tonumber(yearStr)
end
return r
end
local function centuries(year)
local r
if centuryInEpoch(year) == 1 then
if epoch(year) == BC then
r = centuryLink(-150, '') .. SEP .. "'''" ..
centuryLink( -50, BC_LABEL) .. "'''" .. SEP ..
centuryLink( 50, AD_LABEL)
else
r = centuryLink(-50, BC_LABEL) .. SEP .. "'''" ..
centuryLink( 50, AD_LABEL) .. "'''" .. SEP ..
centuryLink(150, '')
end
else
r = ''
local first = -1
local last = 1
for co = first, last do
local cl = centuryLink(year + co * 100, '')
if (co == 0) then
r = r .. "'''" .. cl .. "'''"
else
r = r .. cl
end
if (co ~= last) then
r = r .. SEP
end
end
end
return r
end
local function decades(year)
local first = -1
local last = 1
local r = ''
for offset = first, last do
local f
if (year >= bc(9) and year <= 9) and (offset == 1 or offset == -1) then
f = 9
else
f = 10
end
local ds = decadeLink(year + offset * f)
if (offset == 0) then
r = r .. "'''" .. ds .. "'''"
else
r = r .. ds
end
if (offset ~= last) then
r = r .. SEP
end
end
return r
end
local function years(year)
local first = -3;
local last = 3;
local r = ''
for yo = first, last do
local label
if (yo == first) then
label = "<<"
elseif (yo == first + 1) then
label = "<"
elseif (yo == last - 1) then
label = ">"
elseif (yo == last) then
label = ">>"
end
local yl = yearLink(year + yo, label);
if (yo == 0) then
r = r .. "'''" .. yl .. "'''"
else
r = r .. yl
end
if (yo ~= last) then
r = r .. SEP
end
end
return r
end
local monthName = {'januari', 'februari', 'maart', 'april', 'mei', 'juni', 'juli', 'augustus', 'september', 'oktober', 'november', 'december'}
local monthAbbr = {'jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'}
local function months(year)
if year >= 1900 and year <= tonumber(os.date("%Y")) then
local r = ""
for i = 1, 12 do
r = r .. link(monthName[i] .. ' ' .. year, monthAbbr[i])
if i == 6 then
r = r .. ' <br />'
elseif i ~= 12 then
r = r .. ' · '
end
end
return r
end
end
local function duo(year, offset)
if year > offset then
return (year - offset) .. " – " .. (year - offset + 1)
elseif year == offset then
return 1
end
end
-- for Roman and Armenian numerals
local function nonPositionalDigit(tab, year, div)
if year < div then
return ''
end
return tab[math.floor(year / div) % (#tab + 1)] or ''
end
-- for Eastern Arabic and Arabic-Indian numerals
local function positionalDigit(zero, year)
year = tostring(year)
local r = ""
for i = 1, #year do
r = r .. mw.ustring.char(string.byte(year, i) + zero - 0x30) -- maakt gebruik van Unicode-codepoints
end
return r
end
local function duoPositionalDigit(zero, year, offset)
if year > offset then
return "<br />" .. positionalDigit(zero, year - offset) .. " – " .. positionalDigit(zero, year - offset + 1)
elseif year == offset then
return " " .. positionalDigit(zero, 1)
end
end
local ro4 = {'M', 'MM', 'MMM', 'MMMM'} -- thousands
local ro3 = {'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'} -- hundreds
local ro2 = {'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'} -- tens
local ro1 = {'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'} -- ones
local function romanNumeral(i)
if i > 0 and i < 5000 then
local ro =
nonPositionalDigit(ro4, i, 1000) ..
nonPositionalDigit(ro3, i, 100) ..
nonPositionalDigit(ro2, i, 10) ..
nonPositionalDigit(ro1, i, 1)
return ro
end
end
-- Ab urbe condita
local function auc(year)
if year > bc(754) then
year = year + 753
return year .. " '''" .. romanNumeral(year) .. "'''"
end
end
local ar5 = {'Օ', 'Ֆ'} -- ten-thousands
local ar4 = {'Ռ', 'Ս', 'Վ', 'Տ', 'Ր', 'Ց', 'Ւ', 'Փ', 'Ք'} -- thousands
local ar3 = {'Ճ', 'Մ', 'Յ', 'Ն', 'Շ', 'Ո', 'Չ', 'Պ', 'Ջ'} -- hundreds
local ar2 = {'Ժ', 'Ի', 'Լ', 'Խ', 'Ծ', 'Կ', 'Հ', 'Ձ', 'Ղ'} -- tens
local ar1 = {'Ա', 'Բ', 'Գ', 'Դ', 'Ե', 'Զ', 'Է', 'Ը', 'Թ'} -- ones
local function ak(year)
if year > 0 and year < 30000 then
return nonPositionalDigit(ar5, year, 10000) ..
nonPositionalDigit(ar4, year, 1000) ..
nonPositionalDigit(ar3, year, 100) ..
nonPositionalDigit(ar2, year, 10) ..
nonPositionalDigit(ar1, year, 1)
end
end
local function armenian(year)
year1 = math.floor((math.floor(year * 0.25 - 0.25) - math.floor(year * 0.01 - 0.01) + math.floor(year * 0.0025 - 0.0025)) / 365 + year - 551.8958904)
year2 = math.floor((math.floor(year * 0.25) - math.floor(year * 0.01) + math.floor(year * 0.0025)) / 365 + year - 550.8986301)
if year1 > 0 and year1 ~= year2 then
return year1 .. " – " .. year2 .. "<br /><small>''ԹՎ " .. ak(year1) .. " – " .. ak(year2) .. "''</small>"
elseif year1 > 0 then
return year1 .. " <small>''ԹՎ " .. ak(year1) .. "''</small>"
elseif year1 == 0 then
return year2 .. " <small>''ԹՎ " .. ak(year2) .. "''</small>"
end
end
local cn10 = {'庚', '辛', '壬', '癸', '甲', '乙', '丙', '丁', '戊', '己'}
local cn12 = {'亥', '子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌'}
local function chinese(year)
year = year + 2696
return year .. ' – ' .. (year + 1) .. "<br />" .. link('Chinese astrologie',
cn10[ year % 10 + 1] .. cn12[ year % 12 + 1] .. ' – ' ..
cn10[(year + 1) % 10 + 1] .. cn12[(year + 1) % 12 + 1])
end
local function christian(year, gregcal)
if year > 0 then
local r
if gregcal then
r = link(gregcal, year)
else
r = tostring(year)
end
return r .. " '''" .. romanNumeral(year) .. "'''"
end
end
local function ethiopian(year)
return duo(year, 8)
end
local function hebrew(year)
return duo(year, -3760)
end
local function vikram(year)
return duo(year, -55)
end
local function shaka(year)
return duo(year, 78)
end
local function kali(year)
return duo(year, -3101)
end
local ir = 0x6f0 -- U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO
local function iranian(year)
if year >= 622 then
return duo(year, 622) .. duoPositionalDigit(ir, year, 622)
end
end
local ar = 0x660 -- U+0660 ARABIC-INDIC DIGIT ZERO
local function islamic(year)
local year1 = math.floor( 1.030684 * ( year - 621.5643 ) )
local year2 = math.floor( 1.030684 * ( year - 621.5643 + 1 ) )
if year > 622 then
return year1 .. " – " .. year2 .. "<br />" .. positionalDigit(ar, year2) .. " – " .. positionalDigit(ar, year1) -- Oost-Arabische cijfers omgedraaid zodat dit visueel overeenkomt met West-Arabische cijfers erboven
elseif year == 622 then
return "1 ١"
end
end
local function masonic(year)
return duo(year, -3999)
end
local function themes(year)
local r = ""
for i = 1, #themesTab do
local label = themesTab[i][1]
local prefix = themesTab[i][2]
local title = (prefix or label) .. ' ' .. year
if mw.title.new(title).exists then
r = r .. '|-\n|colspan="3"|' .. link(title, label) .. '\n'
end
end
return r
end
local weekday = {'zon', 'maan', 'dins', 'woens', 'donder', 'vrij', 'zater'}
local CAL_ICON = '[[Bestand:Crystal Clear mimetype vcalendar.png|40px]]'
local function julianCalendar(year)
if year > 3 and year < 1923 then
local v
if year % 4 == 0 then
v = 'schrikkel'
else
v = 'gewoon '
end
local wd = weekday[(3 + math.floor((year + 1) * 5 / 4 + 0.5)) % 7 + 1]
local title = 'kalender van een ' .. v .. 'jaar dat op ' .. wd .. 'dag begint'
local label = 'Juliaanse kalender van ' .. year
return CAL_ICON .. " '''" .. link(title, label) .. "'''"
end
end
local function transitionCalendar(year)
local r = ""
if transitionTab[year] then
if table.maxn(transitionTab[year]) == 1 then
r = link('Overgangskalender van ' .. year, transitionTab[year][1])
elseif table.maxn(transitionTab[year]) > 1 then
for i = 1, table.maxn(transitionTab[year]) do
r = r .. link('Overgangskalender van ' .. year .. ' (' .. transitionTab[year][i] .. ')', transitionTab[year][i])
if i ~= table.maxn(transitionTab[year]) then
r = r .. ' · '
end
end
end
end
if year > 1699 and year < 1712 then
if r ~= "" then
r = r .. ' · '
end
if year % 4 == 0 and year ~= 1700 then
v = 'schrikkel'
else
v = 'gewoon '
end
local i
if year == 1700 then
i = 3
else
i = 2
end
local wd = weekday[(i + math.floor((year + 1) * 5 / 4 + 0.5)) % 7 + 1]
r = r .. link('kalender van een ' .. v .. 'jaar dat op ' .. wd .. 'dag begint', 'Zweden')
end
return r
end
local function gregorianCalendar(year)
if year > 1582 then
local v
if (year % 4)==0 and ((year % 100)~=0 or (year % 400)==0) then
v = 'schrikkel'
else
v = 'gewoon '
end
local wd = weekday[(math.floor((year - 1) / 400) - math.floor((year - 1) / 100) + math.floor((year + 1) * 5 / 4 - 1.5)) % 7 + 1]
local title = 'kalender van een ' .. v .. 'jaar dat op ' .. wd .. 'dag begint'
local label = 'Gregoriaanse kalender van ' .. year
return CAL_ICON .. " '''" .. link(title, label) .. "'''"
end
end
local function row12(left, right, style)
local r = '|-'
if style then
r = r .. ' style="' .. style .. ';"\n'
else
r = r .. '\n'
end
r = r .. '| align="right" | ' .. "<small>'''" .. left .. "'''</small>\n"
r = r .. '| align="center" colspan="2" | ' .. right .. '\n'
return r
end
local function row21(left, right, cellStyle)
local cellArgs = 'style="' .. cellStyle .. '"'
local r = '|- valign="top"\n'
r = r .. '| ' .. cellArgs .. ' colspan="2" | ' .. left .. '\n'
r = r .. '| ' .. cellArgs .. ' | ' .. right .. '\n'
return r
end
local function row21a(left, right)
return row21(left, right, 'border-top:solid 1px #ccd2d9; padding:0.4em 1em 0.4em 0;')
end
local function row21b(left, right)
return row21(left, right, 'padding:0 1em 0 0;')
end
local function row3(text)
return '|-\n| style="' .. TITLEBARCOLOR .. '" colspan="3" align="center" | ' .. text .. '\n'
end
local function zijbalk_jaar(yearStr, year, epo1, epo2)
local r
-- start table
r = '{| class="toccolours vatop" border="0" cellpadding="2" cellspacing="0" ' ..
'align="right" style="margin:0 0 1em 2em; clear:right; font-size:90%; ' ..
INFOBOX_WIDTH .. '\n'
-- heading
r = r .. '| style="' .. TITLEBARCOLOR .. '" colspan="3" align="center" | ' ..
"<big>'''" .. yearInEpoch(year)
if year <= bc(1) then
r = r .. " voor Christus"
end
r = r .. "'''</big>\n"
-- set width
-- zo wordt de 2e kolom breder en komt de 1e kolom niet in de verdrukking
r = r .. '|-\n|\n|width="90px" |\n|\n'
-- navigation
r = r .. row12('[[Lijst van eeuwen|Eeuwen]]:', centuries(year)) ..
row12('[[Lijst van decennia|Decennia]]:', decades(year)) ..
row12('Jaren:', years(year))
local s
s = months(year)
if s then
r = r .. row12('Maanden:', s)
end
-- conversion
r = r .. row3("[[Bestand:Calendar-nl.svg]] '''Jaartelling in verschillende culturen'''") ..
'|-\n|\n'
-- vanaf hier moest eigenlijk uitklapbaar, maar dat heb ik nog niet aan de praat gekregen
s = auc(year)
if s then
r = r .. row21a('[[Ab urbe condita (jaartelling)|Ab urbe condita]]:', s)
end
s = armenian(year)
if s then
r = r .. row21a('[[Armeense kalender|Armeense jaartelling]]:', s)
end
if epo1 and #epo1 > 0 then
r = r .. '|- valign="top"\n' ..
'| style="border-top:solid 1px #ccd2d9; padding:0.4em 1em 0.4em 0;" colspan="3" | [[Eponiemenlijsten|Assyrisch eponiem]]:\n' ..
'|-\n' ..
'| style="padding:0.4em 1em 0.4em 0; text-align:right;" colspan="3" | ' .. epo1
if epo2 and #epo2 > 0 then
r = r .. '<br />' .. epo2 .. '\n'
end
end
s = chinese(year)
if s then
r = r .. row21a('[[Chinese kalender|Chinese jaartelling]]:', s)
end
s = christian(year)
if s then
r = r .. row21a('[[Christelijke jaartelling]]:', s)
end
s = ethiopian(year)
if s then
r = r .. row21a('[[Ethiopische kalender|Ethiopische jaartelling]]:', s)
end
s = hebrew(year)
if s then
r = r .. row21a('[[Joodse kalender|Hebreeuwse jaartelling]]:', s)
end
local hv = vikram(year)
local hs = shaka(year)
local hk = kali(year)
if hv or hs or hk then
r = r .. row21a('[[Hindoekalender]]s:', '')
if hv then
r = r .. row21b("- ''[[Vikram Samvat]]''", hv)
end
if hs then
r = r .. row21b("- ''[[Indiase kalender|Shaka Samvat]]''", hs)
end
if hk then
r = r .. row21b("- ''[[Kali yuga]]''", hk)
end
end
s = iranian(year)
if s then
r = r .. row21a('[[Iraanse kalender|Iraanse jaartelling]]:', s)
end
s = islamic(year)
if s then
r = r .. row21a('[[Islamitische kalender|Islamitische jaartelling]]:', s)
end
s = masonic(year)
if s then
r = r .. row21a('[[Maçonnieke kalender|Maçonnieke jaartelling]]:', s)
end
-- XXX footnotes unused
-- subjects by year
s = themes(yearStr)
if s and s ~= "" then
r = r .. row3("[[Bestand:Nuvola apps kuser.svg|25px]] '''" ..
yearStr .. " naar onderwerp''' [[Bestand:Gnome-globe.svg|25px]]") .. s
end
-- calendars
s = julianCalendar(year)
if s then
r = r .. row3(s)
end
s = transitionCalendar(year)
if s and s ~= "" then
r = r .. row3('Overgangskalenders:') .. row3("'''" .. s .. "'''")
end
s = gregorianCalendar(year)
if s then
r = r .. row3(s)
end
-- terminate table
r = r .. '|}'
return r
end
-- exported functions
-- argument is a year string, e.g. "22 v.Chr."
function p.zijbalk_jaar(frame)
frame = frame:getParent() -- intended to be called via a template
local yearStr = frame.args[1]
if not yearStr or #yearStr == 0 then
yearStr = tostring(mw.title.getCurrentTitle())
end
local yearNum = yearNumber(yearStr)
if yearNum then
local epo1 = frame.args['epo1']
local epo2 = frame.args['epo2']
return zijbalk_jaar(yearStr, yearNum, epo1, epo2)
else
return frame:expandTemplate{title='Error', args = {'Fout: ongeldig jaar: ' .. yearStr}}
end
end
return p