Jump to content

Module:Year in various calendars

Permanently protected module
From Wikipedia, the free encyclopedia

-- Load dependencies.
localgetArgs=require('Module:Arguments').getArgs
localnumToRoman=require('Module:Roman').main
localgetOlympiad=require('Module:Ancient Olympiads')._main
localgetDynasty=require('Module:Ancient Egypt era')._main
localgetPharaoh=require('Module:Ancient Egypt kings')._main
localnumToArmenian=require('Module:Armenian').main
localgetRegnal=require('Module:British regnal year').main
localjapaneseEra=require('Module:Japanese calendar').era()

-- Define constants.
locallang=mw.language.getContentLanguage()
localcurrentYear=tonumber(lang:formatDate('Y'))

--------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------

localfunctionisInteger(num)
-- Checks if a value is an integer. If so, returns the value converted to a number.
-- If not, returns false.
num=tonumber(num)
ifnumandmath.floor(num)==numandnum~=math.hugethen
returnnum
else
returnfalse
end
end

localfunctionBCToNum(s)
-- Converts strings of the format "n BC" to their corresponding
-- numerical values.
iftype(s)~='string'then
returnnil
end
s=mw.ustring.match(mw.ustring.upper(s),'^([1-9]%d*)%s*BC$')
ifnotsthen
returnnil
end
localnum=tonumber(s)
num=(num-1)*-1
returnnum
end

localfunctionnumToBC(num)
-- For BC years, returns a string with the year name appended with "BC".
-- Otherwise returns nil.
num=isInteger(num)
ifnotnumthenreturnend
ifnum<=0then
returnstring.format('%d BC',1-num)
end
end

localfunctionADToNum(s)
-- Converts strings of the format "AD n"
-- to their corresponding numerical values.
iftype(s)~='string'then
returnnil
end
s=mw.ustring.match(mw.ustring.upper(s),'^AD%s*([1-9]%d*)$')
ifnotsthen
returnnil
end
localnum=tonumber(s)
returnnum
end

localfunctionnumToAD(num)
-- For AD years up to 100, returns a string with the year name prepended with "AD".
-- Otherwise returns nil.
num=isInteger(num)
ifnotnumthenreturnend
if(num<=100)then
returnstring.format('AD %d',num)
end
end

localfunctionformatNegative(s)
-- Replaces hyphens in a string with minus signs if the hyphen comes before a number.
s=mw.ustring.gsub(s,'%-(%d)','−%1')
returns
end

--------------------------------------------------------------------
-- Calendar box class definition
--------------------------------------------------------------------

localcalendarBox={}
calendarBox.__index=calendarBox

functioncalendarBox:new(init)
init=type(init)=='table'andinitor{}
localobj={}
localpagename=mw.title.getCurrentTitle().text

-- Set the year. If the year is specified as an argument, use that.
-- Otherwise, use the page name if it is valid. If the pagename isn't
-- valid, use the current year.
localyearNum=isInteger(init.year)
localyearBC=BCToNum(init.year)
localyearAD=ADToNum(init.year)
localpageNum=isInteger(pagename)
localpageBC=BCToNum(pagename)
localpageAD=ADToNum(pagename)
ifyearNumthen-- First, see if the year parameter is a number.
self.year=yearNum
elseifyearBCthen-- Second, see if the year parameter is a "yyyy BC" string.
self.year=yearBC
elseifyearADthen-- Third, see if the year parameter is an AD/CE/year string.
self.year=yearAD
elseifpageNumthen-- Fourth, see if the pagename is an integer.
self.year=pageNum
elseifpageBCthen-- Fifth, see if the pagename is a "yyyy BC" string.
self.year=pageBC
elseifpageADthen-- Sixth, see if the pagename is an AD/CE/year string.
self.year=pageAD
else
self.year=currentYear-- If none of the above apply, use the current year.
end

-- Set year text values.
self.BCYearName=numToBC(self.year)
self.ADYearName=numToAD(self.year)
ifself.BCYearNamethen
self.yearText=self.BCYearName
elseifself.ADYearNamethen
self.yearText=self.ADYearName
else
self.yearText=tostring(self.year)
end

-- Set other fields.
self.caption=self.yearText
self.footnotes=init.footnotes

returnsetmetatable(obj,{
__index=self
})
end

functioncalendarBox:setCaption(s)
-- Sets the calendar box caption.
iftype(s)~='string'ors==''thenreturnend
self.caption=s
end

functioncalendarBox:addCalendar(obj)
-- Adds a calendar or a calendar group.
iftype(obj)~='table'andtype(obj.new)~='function'thenreturnend-- Exit if the object is invalid.
self.calendars=self.calendarsor{}
table.insert(self.calendars,obj)
end

-- Add an alias for adding calendar groups. The function is the same, but it might be confusing for users
-- to have to use the name "addCalendar" for a calendar group.
calendarBox.addCalendarGroup=calendarBox.addCalendar

functioncalendarBox:export()
-- Outputs the calendar box wikitext.
localroot=mw.html.create('table')
-- Export the calendar box headers.
root
:addClass('infobox vevent')
:css('width','22em')
:tag('caption')
:css('font-size','125%')
:tag('span')
:addClass('summary dtstart')
:wikitext(self.caption)

-- Export the calendars and calendar groups. "calendar:export()" works for both kinds
-- of objects. Some export functions can return nil, so we need to check for that.
iftype(self.calendars)=='table'then
for_,calendarinipairs(self.calendars)do
localcalendarText=calendar:export()
iftype(calendarText)=='string'then
root:wikitext(calendarText)
end
end
end

-- Add footnotes.
iftype(self.footnotes)=='string'andself.footnotes~=''then
root
:tag('tr')
:tag('td')
:attr('colspan','2')
:wikitext(string.format('%s',self.footnotes))
end

returntostring(root)
end

--------------------------------------------------------------------
-- Calendar group class definition
--------------------------------------------------------------------

-- Calendar groups are used to group different calendars together.
-- Previously, the template did this by including a table row with
-- no year value. By using objects we can do the same thing more
-- semantically.

localcalendarGroup={}
calendarGroup.__index=calendarGroup

functioncalendarGroup:new(init)
init=type(init)=='table'andinitor{}
localobj={}

-- Get the heading and throw an error if it is invalid.
obj.heading=init.heading
iftype(obj.heading)~='string'then
error('calendarGroup: no heading detected')
end

-- Set the metatable and return the object.
self.__index=self
returnsetmetatable(obj,{
__index=self
})
end

functioncalendarGroup:addCalendar(calendar)
-- Adds a calendar object to the calendar group.
self.calendars=self.calendarsor{}
iftype(calendar)=='table'andtype(calendar.getLink)=='function'then
table.insert(self.calendars,calendar)
end
end

functioncalendarGroup:export()
-- Exports the calendar group's wikitext.
-- Indent and italicise each calendar's link if it exists.
fori,calendarinipairs(self.calendars)do
locallink=calendar:getLink()
iftype(link)=='string'then
self.calendars[i]:setRawLink(string.format("&nbsp;- ''%s''",link))
end
end
-- Create the heading row html and export the calendar objects.
localret=mw.html.create()
ret
:tag('tr')
:tag('td')
:wikitext(self.heading)
:done()
:tag('td')-- Use a blank tag to make the html look nice.
:allDone()
for_,calendarinipairs(self.calendars)do
ret:wikitext(calendar:export())
end
returntostring(ret)
end

--------------------------------------------------------------------
-- Calendar class definition
--------------------------------------------------------------------

localcalendar={}
calendar.__index=calendar
calendar.type='calendar'

functioncalendar:new()
localobj={}
returnsetmetatable(obj,{
__index=self
})
end

functioncalendar:setLink(link,display)
-- Sets the calendar's wikilink, with optional display text and italics.
iftype(link)~='string'orlink==''thenreturnend
display=type(display)=='string'anddisplay~=''anddisplay
ifdisplaythen
self.link=string.format('[[%s|%s]]',link,display)
else
self.link=string.format('[[%s]]',link)
end
end

functioncalendar:setRawLink(s)
-- Sets the calendar's wikilink as raw wikitext.
iftype(s)~='string'ors==''thenreturnend
self.link=s
end

functioncalendar:getLink()
-- Returns the calendar's link value.
returnself.link
end

functioncalendar:setYear(year)
-- Sets a single year. Can be passed either a string or a number.
-- If passed as a number, it is formatted with minus signs instead of hyphens.
-- If passed as a string, no minus-sign formatting occurs; this should be done in the individual calendar definitions.
iftype(year)=='number'then
year=tostring(year)
self.year=formatNegative(year)
elseiftype(year)=='string'then
self.year=year
end
end

functioncalendar:setYearRange(year1,year2)
-- Sets a year range. Must be passed two numbers.
iftype(year1)=='number'andtype(year2)=='number'then
localyear
ifyear1<0oryear2<0then-- Leave a gap for negative years to avoid having a minus sign and a dash right next to each other.
year=string.format('%d – %d',year1,year2)
year=formatNegative(year)
else
year=string.format('%d–%d',year1,year2)
end
self.year=year
end
end

functioncalendar:setYearCouple(year1,year2,addtext)
-- Same as setYearRange, only with a slash (/) in the middle. Must be passed two numbers.
-- Additional text possible, must be defined as follows: addtext = string.format( 'additional text or link')
-- See example in Seleucid era calendar
iftype(year1)=='number'andtype(year2)=='number'then
localyear
ifyear1<0oryear2<0then-- Leave no gap for negative years.
year=string.format('%d/%d %s',year1,year2,addtext)
year=formatNegative(year)
else
year=string.format('%d/%d %s',year1,year2,addtext)
end
self.year=year
end
end

functioncalendar:export()
-- Outputs the calendar wikitext.
-- Exit if no link has been specified.
locallink=self.link
iftype(link)~='string'orlink==''thenreturnend

-- If no year has been specified, set the year value to N/A.
localyear=self.year
iftype(year)~='string'oryear==''then
year="''N/A''"
end

-- Build the table row.
localret=mw.html.create()
ret
:tag('tr')
:tag('td')
:wikitext(link)
:done()
:tag('td')
:wikitext(year)
:allDone()
returntostring(ret)
end

--------------------------------------------------------------------
-- Build the box
--------------------------------------------------------------------

localfunctionmakeCalendarBox(args)
-- Initiate the box and get the year values.
localinit=args
localbox=calendarBox:new(init)
localyear=box.year
localyearText=box.yearText

-- Set the caption.
box:setCaption(box.caption..' in various [[Calendar era|calendars]]')

----------------------------------------------------------------------
-- Gregorian calendar
----------------------------------------------------------------------

localgregorian=calendar:new()
gregorian:setLink('Gregorian calendar')
-- Get the year link.
localgregcal=args.gregcal
iftype(gregcal)=='string'andgregcal~=''then
gregorian.yearLink=string.format('[[%s|%s]]',gregcal,yearText)
else
gregorian.yearLink=yearText
end
-- Set the year.
ifyear<=0then
gregorian.romanYear=numToRoman{-(year-1)}..' BC'
else
gregorian.romanYear=numToRoman{year}
end
ifgregorian.romanYearthen
gregorian:setYear(string.format(
[[%s<br /><span style= "font-family: serif;" >''%s''</span>]],
gregorian.yearLink,gregorian.romanYear
))
else
gregorian:setYear(gregorian.yearLink)
end
box:addCalendar(gregorian)

----------------------------------------------------------------------
-- French Republican calendar
-- displays only in years 1793 - 1805 and 1871
-- This calendar was in use and had defined years only for the short period on display.
-- Its importance during these few years is also the reason why it should stay out of the alphabetic order.
-- See discussion on talk page.
----------------------------------------------------------------------

ifyear>=1793andyear<1806oryear==1871then
localrepublican=calendar:new()
republican:setLink('French Republican calendar')
ifyear<=1870then
republican:setYearRange(year-1792,year-1791)
elseifyear==1871then
republican:setYear(year-1792)-- Paris Commune, May
end
box:addCalendar(republican)
end

----------------------------------------------------------------------
-- Ab urbe condita
-- Varro's correlation, from 1 AUC
----------------------------------------------------------------------
ifyear>=-752then
localabUrbe=calendar:new()
abUrbe:setLink('Ab urbe condita')
abUrbe:setYear(year+753)
box:addCalendar(abUrbe)
end

----------------------------------------------------------------------
-- Ancient Egypt era
-- Displays dynasty between 1549 BC and 30 BC
-- Displays pharaoh or king between 752 BC and 30 BC
----------------------------------------------------------------------
ifyear>-1549andyear<=-29then
localancEgypt=calendar:new()
ancEgypt:setLink(
'Egyptian chronology',
'Ancient Egypt era'
)
ancEgypt:setYear(getDynasty(year))
box:addCalendar(ancEgypt)
end
ifyear>-752andyear<=-29then
localancPharaoh=calendar:new()
ancPharaoh:setLink(
'List of pharaohs',
'<i>- Pharaoh</i>'
)
ancPharaoh:setYear(getPharaoh(year))
box:addCalendar(ancPharaoh)
end

----------------------------------------------------------------------
-- Ancient Olympiads
-- Currently only the first 194 Olympiads
-- May be expanded until 394 AD when data available
----------------------------------------------------------------------
ifyear>=-1300andyear<1then
localancOlympiads=calendar:new()
ancOlympiads:setLink(
'Ancient Greek calendar',
'Ancient Greek era'
)
ancOlympiads:setYear(getOlympiad(year))
box:addCalendar(ancOlympiads)
end

----------------------------------------------------------------------
-- Armenian calendar
----------------------------------------------------------------------

ifyear>551then
localarmenian=calendar:new()
armenian:setLink('Armenian calendar')
localarmenianYear=year-551
armenian:setYear(string.format('%s<br />ԹՎ %s',armenianYear,numToArmenian(armenianYear)))
box:addCalendar(armenian)
end

----------------------------------------------------------------------
-- Assyrian calendar
----------------------------------------------------------------------

localassyrian=calendar:new()
assyrian:setLink('Assyrian calendar')
assyrian:setYear(year+4750)
box:addCalendar(assyrian)

----------------------------------------------------------------------
-- Bahá'í calendar
-- displays only after 1843
----------------------------------------------------------------------

ifyear>=1844then
localbahai=calendar:new()
bahai:setLink("Baháʼí calendar")
bahai:setYearRange(year-1844,year-1843)
box:addCalendar(bahai)
end

----------------------------------------------------------------------
-- Balinese saka calendar
----------------------------------------------------------------------
localbalinese=calendar:new()
balinese:setLink('Balinese saka calendar')
ifyear-76>0then
balinese:setYearRange(year-79,year-78)
end
box:addCalendar(balinese)

----------------------------------------------------------------------
-- Bengali calendar
----------------------------------------------------------------------

localbengali=calendar:new()
bengali:setLink('Bengali calendar')
bengali:setYear(year-593)
box:addCalendar(bengali)

----------------------------------------------------------------------
-- Berber calendar
----------------------------------------------------------------------

localberber=calendar:new()
berber:setLink('Berber calendar')
berber:setYear(year+950)
box:addCalendar(berber)

----------------------------------------------------------------------
-- Regnal year
----------------------------------------------------------------------

ifyear>=1000then
localregnal=calendar:new()
localregnalName
ifyear>1706then
regnalName='British'
else
regnalName='English'
end
regnal:setLink('Regnal years of English and British monarchs',regnalName..' Regnal year')
regnal:setYear(getRegnal(year))
box:addCalendar(regnal)
end

----------------------------------------------------------------------
-- Buddhist calendar
----------------------------------------------------------------------

localbuddhist=calendar:new()
buddhist:setLink('Buddhist calendar')
buddhist:setYear(year+544)
box:addCalendar(buddhist)

----------------------------------------------------------------------
-- Burmese calendar
----------------------------------------------------------------------

localburmese=calendar:new()
burmese:setLink('Burmese calendar')
burmese:setYear(year-638)
box:addCalendar(burmese)

----------------------------------------------------------------------
-- Byzantine calendar
----------------------------------------------------------------------

localbyzantine=calendar:new()
byzantine:setLink('Byzantine calendar')
byzantine:setYearRange(year+5508,year+5509)
box:addCalendar(byzantine)

----------------------------------------------------------------------
-- Chinese calendar
----------------------------------------------------------------------

localchinese=calendar:new()
chinese:setLink('Chinese calendar')

-- Define the information for the "heavenly stems" and "earthly branches" year cycles.
-- See [[Chinese calendar#Cycle of years]] for information.

localheavenlyStems={
{' giáp ','Wood'},-- 1
{' ất ','Wood'},-- 2
{' bính ','Fire'},-- 3
{' đinh ','Fire'},-- 4
{' mậu ','Earth'},-- 5
{' kỷ ','Earth'},-- 6
{' canh ','Metal'},-- 7
{' tân ','Metal'},-- 8
{' nhâm ','Water'},-- 9
{' quý ','Water'}-- 10
}

localearthlyBranches={
{' tử ','[[Rat (zodiac)|Rat]]'},-- 1
{' sửu ','[[Ox (zodiac)|Ox]]'},-- 2
{' dần ','[[Tiger (zodiac)|Tiger]]'},-- 3
{' mão ','[[Rabbit (zodiac)|Rabbit]]'},-- 4
{' thần ','[[Dragon (zodiac)|Dragon]]'},-- 5
{' tị ','[[Snake (zodiac)|Snake]]'},-- 6
{' ngọ ','[[Horse (zodiac)|Horse]]'},-- 7
{' vị ','[[Goat (zodiac)|Goat]]'},-- 8
{' thân ','[[Monkey (zodiac)|Monkey]]'},-- 9
{' dậu ','[[Rooster (zodiac)|Rooster]]'},-- 10
{' tuất ','[[Dog (zodiac)|Dog]]'},-- 11
{' hợi ','[[Pig (zodiac)|Pig]]'}-- 12
}

-- Calculate the cycle numbers from the year. The first sexagenary year corresponds to the ''previous'' year's entry
-- in [[Chinese calendar correspondence table]], as the Chinese New Year doesn't happen until Jan/Feb in
-- Gregorian years.
localsexagenaryYear1=(year-4)%60
localsexagenaryYear2=(year-3)%60
localheavenlyNum1=(sexagenaryYear1-1)%10+1-- amod, since lua arrays are 1-indexed
localheavenlyNum2=(sexagenaryYear2-1)%10+1
localearthlyNum1=(sexagenaryYear1-1)%12+1
localearthlyNum2=(sexagenaryYear2-1)%12+1

-- Get the data tables for each permutation.
localheavenlyTable1=heavenlyStems[heavenlyNum1]
localheavenlyTable2=heavenlyStems[heavenlyNum2]
localearthlyTable1=earthlyBranches[earthlyNum1]
localearthlyTable2=earthlyBranches[earthlyNum2]

-- Work out the continously-numbered year. (See [[Chinese calendar#Continuously numbered years]].)
localyear1=year+2697
localyear2=year+2698
localyear1Alt=year1-207
localyear2Alt=year2-207

-- Format any negative numbers.
year1=formatNegative(tostring(year1))
year2=formatNegative(tostring(year2))
year1Alt=formatNegative(tostring(year1Alt))
year2Alt=formatNegative(tostring(year2Alt))

-- Return all of that data in a (hopefully) reader-friendly format.
chinese:setYear(string.format(
[=[[[Sexagenary cycle|%s%s]] niên (%s&nbsp;%s)<br />%s or %s<br />&nbsp;&nbsp;&nbsp;&nbsp;''—&nbsp;to&nbsp;—''<br />%s%s niên (%s&nbsp;%s)<br />%s or %s]=],
heavenlyTable1[1],
earthlyTable1[1],
heavenlyTable1[2],
earthlyTable1[2],
year1,
year1Alt,
heavenlyTable2[1],
earthlyTable2[1],
heavenlyTable2[2],
earthlyTable2[2],
year2,
year2Alt
))

box:addCalendar(chinese)

----------------------------------------------------------------------
-- Coptic calendar
----------------------------------------------------------------------

localcoptic=calendar:new()
coptic:setLink('Coptic calendar')
coptic:setYearRange(year-284,year-283)
box:addCalendar(coptic)

----------------------------------------------------------------------
-- Discordian calendar
----------------------------------------------------------------------

localdiscordian=calendar:new()
discordian:setLink('Discordian calendar')
discordian:setYear(year+1166)
box:addCalendar(discordian)

----------------------------------------------------------------------
-- Ethiopian calendar
----------------------------------------------------------------------

localethiopian=calendar:new()
ethiopian:setLink('Ethiopian calendar')
ethiopian:setYearRange(year-8,year-7)
box:addCalendar(ethiopian)

----------------------------------------------------------------------
-- Hebrew calendar
----------------------------------------------------------------------

localhebrew=calendar:new()
hebrew:setLink('Hebrew calendar')
hebrew:setYearRange(year+3760,year+3761)
box:addCalendar(hebrew)

----------------------------------------------------------------------
-- Hindu calendars
----------------------------------------------------------------------

localhindu=calendarGroup:new{heading='[[Hindu calendar]]s'}

-- Vikram Samvat

localvikramSamvat=calendar:new()
vikramSamvat:setLink('Vikram Samvat')
vikramSamvat:setYearRange(year+56,year+57)
hindu:addCalendar(vikramSamvat)

-- Shaka Samvat

localshakaSamvat=calendar:new()
shakaSamvat:setLink('Indian national calendar','Shaka Samvat')
ifyear>=78then
shakaSamvat:setYearRange(year-79,year-78)
end
hindu:addCalendar(shakaSamvat)

-- Kali Yuga

localkaliYuga=calendar:new()
kaliYuga:setLink('Kali Yuga')-- use italics
kaliYuga:setYearRange(year+3100,year+3101)
hindu:addCalendar(kaliYuga)

box:addCalendarGroup(hindu)

----------------------------------------------------------------------
-- Holocene calendar
----------------------------------------------------------------------

localholocene=calendar:new()
holocene:setLink('Holocene calendar')
holocene:setYear(year+10000)
box:addCalendar(holocene)

----------------------------------------------------------------------
-- Igbo calendar
----------------------------------------------------------------------

-- In the old template this was a calendar group with just one calendar; intentionally adding this as a single
-- calendar here, as the previous behaviour looked like a mistake.
ifyear>=1000then
localigbo=calendar:new()
igbo:setLink('Igbo calendar')
igbo:setYearRange(year-1000,year-999)
box:addCalendar(igbo)
end

----------------------------------------------------------------------
-- Iranian calendar
----------------------------------------------------------------------

localiranian=calendar:new()
iranian:setLink('Iranian calendars','Iranian calendar')
ifyear-621>0then
iranian:setYearRange(year-622,year-621)
else
iranian:setYear(string.format('%d BP&nbsp;– %d BP',622-year,621-year))
end
box:addCalendar(iranian)

----------------------------------------------------------------------
-- Islamic calendar
----------------------------------------------------------------------

localislamic=calendar:new()
islamic:setLink('Islamic calendar')
localislamicMult=1.030684-- the factor to multiply by
localislamicSub=621.5643-- the factor to subtract by
ifyear-621>0then
localyear1=math.floor(islamicMult*(year-islamicSub))
localyear2=math.floor(islamicMult*(year-islamicSub+1))
islamic:setYearRange(year1,year2)
else
localyear1=math.ceil(-islamicMult*(year-islamicSub))
localyear2=math.ceil(-islamicMult*(year-islamicSub+1))
islamic:setYear(string.format('%d BH&nbsp;– %d BH',year1,year2))
end
box:addCalendar(islamic)

----------------------------------------------------------------------
-- Japanese calendar
-- starting 600
----------------------------------------------------------------------

ifyear>=600then
localjapanese=calendar:new()
japanese:setLink('Japanese calendar')

japanese.thisEra=japaneseEra:new{year=year}
ifjapanese.thisErathen
localjapaneseYearText={}
japanese.oldEra=japanese.thisEra:getOldEra()
ifjapanese.oldEraandjapanese.oldEra.eraYearandjapanese.thisEra.article~=japanese.oldEra.articlethen
japanese.oldText=string.format('%s %d',japanese.oldEra.link,japanese.oldEra.eraYear)
table.insert(japaneseYearText,japanese.oldText)
table.insert(japaneseYearText,' / ')
end
ifjapanese.thisEra.eraYearthen
table.insert(japaneseYearText,string.format('%s %d',japanese.thisEra.link,japanese.thisEra.eraYear))
end
table.insert(japaneseYearText,string.format('<br />(%s%s niên )',japanese.thisEra.kanji,japanese.thisEra.eraYearKanji))
japanese:setYear(table.concat(japaneseYearText))
end

box:addCalendar(japanese)
end

----------------------------------------------------------------------
-- Javanese calendar
----------------------------------------------------------------------

localjavanese=calendar:new()
javanese:setLink('Javanese calendar')
localjavaneseMult=1.030684-- the factor to multiply by
localjavaneseSub=124.9-- the factor to subtract by
ifyear-124>0then
localyear1=math.floor(javaneseMult*(year-javaneseSub))
localyear2=math.floor(javaneseMult*(year-javaneseSub+1))
javanese:setYearRange(year1,year2)
else
localyear1=math.ceil(-javaneseMult*(year-javaneseSub))
localyear2=math.ceil(-javaneseMult*(year-javaneseSub+1))
end
box:addCalendar(javanese)

----------------------------------------------------------------------
-- Juche calendar
-- displays only after 1910
----------------------------------------------------------------------

ifyear>=1910then
localjuche=calendar:new()
juche:setLink('Juche calendar')
ifyear>1911then
juche:setYear(year-1911)
end
box:addCalendar(juche)
end

----------------------------------------------------------------------
-- Julian calendar
----------------------------------------------------------------------

localjulian=calendar:new()
julian:setLink('Julian calendar')

ifyear>=-45andyear<1582then
julian:setYear(gregorian.year)
elseifyear>=1582then
localdiff=math.floor(year/100-2)-math.floor(year/400)
ifyear%100==0andyear%400~=0then
julian:setYear('Gregorian minus '..diff-1..' or '..diff..' days')
else
julian:setYear('Gregorian minus '..diff..' days')
end
end

box:addCalendar(julian)

----------------------------------------------------------------------
-- Korean calendar
----------------------------------------------------------------------

localkorean=calendar:new()
korean:setLink('Korean calendar')
korean:setYear(year+2333)
box:addCalendar(korean)

----------------------------------------------------------------------
-- Minguo calendar
----------------------------------------------------------------------

localminguo=calendar:new()
minguo:setLink('Minguo calendar')
ifyear>1949then
localminguoYear=year-1911
minguo:setYear(string.format('[[Taiwan|ROC]] %d<br /> dân quốc %d niên ',minguoYear,minguoYear))
elseifyear>1911then
localminguoYear=year-1911
minguo:setYear(string.format('[[Republic of China (1912–1949)|ROC]] %d<br /> dân quốc %d niên ',minguoYear,minguoYear))
else
localminguoYear=1911-year+1
minguo:setYear(string.format('%d before [[Republic of China (1912–1949)|ROC]]<br /> dân tiền %d niên ',minguoYear,minguoYear))
end
box:addCalendar(minguo)

----------------------------------------------------------------------
-- Nanakshahi calendar
----------------------------------------------------------------------

localnanakshahi=calendar:new()
nanakshahi:setLink('Nanakshahi calendar')
nanakshahi:setYear(year-1468)
box:addCalendar(nanakshahi)

----------------------------------------------------------------------
-- Seleucid era
-- displays from 312 BC until 1200 AD
----------------------------------------------------------------------

ifyear>=-311andyear<1200then
localseleucid=calendar:new()
seleucid:setLink('Seleucid era')
localaddtext=string.format('[[Anno Graecorum|AG]]')
seleucid:setYearCouple(year+311,year+312,addtext)
box:addCalendar(seleucid)
end

----------------------------------------------------------------------
-- Thai solar calendar
----------------------------------------------------------------------

localthai=calendar:new()
thai:setLink('Thai solar calendar')
ifyear>=1941then
thai:setYear(year+543)
else-- if year >= 1912 or year <= 1887 -- year started in March/April
thai:setYearRange(year+542,year+543)
-- else -- Rattanakosin Era, 1888?-1912
-- thai:setYear( string.format( '%d &nbsp;– %d ([[Rattanakosin Kingdom|Rattanakosin Era]])', year - 1782, year - 1781 ) )
end
box:addCalendar(thai)

----------------------------------------------------------------------
-- Tibetan calendar
----------------------------------------------------------------------

localtibetan=calendar:new()
tibetan:setLink('Tibetan calendar')

-- Define the information for the "heavenly stems" and "earthly branches" year cycles.
-- See [[Tibetan calendar#Years]] for information.

localheavenlyStems={
{' dương mộc ','male Wood'},-- 1
{' âm mộc ','female Wood'},-- 2
{' dương hỏa ','male Fire'},-- 3
{' âm hỏa ','female Fire'},-- 4
{' dương thổ ','male Earth'},-- 5
{' âm thổ ','female Earth'},-- 6
{' dương kim ','male Iron'},-- 7
{' âm kim ','female Iron'},-- 8
{' dương thủy ','male Water'},-- 9
{' âm thủy ','female Water'}-- 10
}

localearthlyBranches={
{' thử ','[[Rat (zodiac)|Rat]]'},-- 1
{' ngưu ','[[Ox (zodiac)|Ox]]'},-- 2
{' hổ ','[[Tiger (zodiac)|Tiger]]'},-- 3
{' thỏ ','[[Rabbit (zodiac)|Rabbit]]'},-- 4
{' long ','[[Dragon (zodiac)|Dragon]]'},-- 5
{' xà ','[[Snake (zodiac)|Snake]]'},-- 6
{' mã ','[[Horse (zodiac)|Horse]]'},-- 7
{' dương ','[[Goat (zodiac)|Goat]]'},-- 8
{' hầu ','[[Monkey (zodiac)|Monkey]]'},-- 9
{' kê ','[[Rooster (zodiac)|Rooster]]'},-- 10
{' cẩu ','[[Dog (zodiac)|Dog]]'},-- 11
{' trư ','[[Pig (zodiac)|Pig]]'}-- 12
}

-- Calculate the cycle numbers from the year. The first sexagenary year corresponds to the ''previous'' year's entry
-- in [[Tibetan calendar correspondence table]], as the Tibetan New Year doesn't happen until Feb/Mar in
-- Gregorian years.
localsexagenaryYear1=(year-4)%60
localsexagenaryYear2=(year-3)%60
localheavenlyNum1=(sexagenaryYear1-1)%10+1-- amod, since lua arrays are 1-indexed
localheavenlyNum2=(sexagenaryYear2-1)%10+1
localearthlyNum1=(sexagenaryYear1-1)%12+1
localearthlyNum2=(sexagenaryYear2-1)%12+1

-- Get the data tables for each permutation.
localheavenlyTable1=heavenlyStems[heavenlyNum1]
localheavenlyTable2=heavenlyStems[heavenlyNum2]
localearthlyTable1=earthlyBranches[earthlyNum1]
localearthlyTable2=earthlyBranches[earthlyNum2]

-- Work out the continously-numbered year. (See [[Tibetan calendar#Years with cardinal numbers]].)
localyear1=year+126
localyear2=year+127
localyear1Alt1=year1-381
localyear1Alt2=year1-1153
localyear2Alt1=year2-381
localyear2Alt2=year2-1153

-- Format any negative numbers.
year1=formatNegative(tostring(year1))
year2=formatNegative(tostring(year2))
year1Alt1=formatNegative(tostring(year1Alt1))
year1Alt2=formatNegative(tostring(year1Alt2))
year2Alt1=formatNegative(tostring(year2Alt1))
year2Alt2=formatNegative(tostring(year2Alt2))

-- Return all of that data in a (hopefully) reader-friendly format.
tibetan:setYear(string.format(
[=[%s%s niên <br />(%s-%s)<br />%s or %s or %s<br />&nbsp;&nbsp;&nbsp;&nbsp;''—&nbsp;to&nbsp;—''<br />%s%s niên <br />(%s-%s)<br />%s or %s or %s]=],
heavenlyTable1[1],
earthlyTable1[1],
heavenlyTable1[2],
earthlyTable1[2],
year1,
year1Alt1,
year1Alt2,
heavenlyTable2[1],
earthlyTable2[1],
heavenlyTable2[2],
earthlyTable2[2],
year2,
year2Alt1,
year2Alt2
))

box:addCalendar(tibetan)

----------------------------------------------------------------------
-- Unix time
----------------------------------------------------------------------

localunix=calendar:new()

localfunctiongetUnixTime(year)
ifyear<1970thenreturnend
localnoError,unixTime=pcall(lang.formatDate,lang,'U','1 Jan '..tostring(year))
ifnotnoErrorornoErrorandnotunixTimethenreturnend
unixTime=tonumber(unixTime)
ifunixTimeandunixTime>=0then
returnunixTime-1
end
end
unix.thisYear=getUnixTime(year)
unix.nextYear=getUnixTime(year+1)
ifunix.thisYearandunix.nextYearthen
unix:setLink('Unix time')
unix:setYear((unix.thisYear+1).."–"..unix.nextYear)
end

box:addCalendar(unix)

returnbox:export()
end

--------------------------------------------------------------------
-- Process arguments from #invoke
--------------------------------------------------------------------

localp={}

functionp.main(frame)
-- Process the arguments and pass them to the box-building function.
localargs=getArgs(frame)
-- Pass year argument with 'year' parameter or without any name but first argument
args.year=args.yearorargs[1]
returnmakeCalendarBox(args)
end

returnp