This Lua module is used on approximately 2,800 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them. |
This module is rated as beta, and is ready for widespread use. It is still new and should be used with some caution to ensure the results are as expected. |
This module depends on the following other modules: |
Lua error in package.lua at line 80: module 'Module:HtmlBuilder' not found.
Lua error in package.lua at line 80: module 'Module:HtmlBuilder' not found.
This module produces the sidebar opposite displaying a given Gregorian year in various different calendars.
Simple
((#invoke:Year in various calendars|main))
All parameters
((#invoke:Year in various calendars|main |year=(n) |footnotes=(footnotes) |gregcal=(article name)))
The HTML classes of this microformat include:
The module is set up to allow for easy addition of new calendars. Just scroll down to the "Build the box" section of the module code, and add your calendar as follows:
To display one year:
local myCalendar = calendar:new()
myCalendar:setLink( 'My calendar article' ) -- The name of the calendar's Wikipedia article.
myCalendar:setYear( year + 10 ) -- Lua code linking the Gregorian calendar year to your calendar's year.
box:addCalendar( myCalendar )
To display a year range:
local myCalendar = calendar:new()
myCalendar:setLink( 'My calendar article' ) -- The name of the calendar's Wikipedia article.
myCalendar:setYearRange( year + 10, year + 11 ) -- Lua code outputting the start year and the end year of the year range.
box:addCalendar( myCalendar )
More complicated calendars can be passed as a string to calendar:setYear()
.
The module defines three classes which do the work of setting up the sidebar and displaying the data provided by the calendar functions. These are the calendarBox
class, which defines the sidebar; the calendar
class, which holds the data for one calendar; and the calendarGroup
object, which defines a group of calendar objects with a heading.
To load these classes from another module, use the following:
local yearInOtherCalendars = require( 'Module:Year in various calendars' )
local calendarBox = yearInOtherCalendars.calendarBox
local calendarGroup = yearInOtherCalendars.calendarGroup
local calendar = yearInOtherCalendars.calendar
A calendarBox
object is initiated with:
local myCalendarBox = calendarBox:new{ year = yyyy, footnotes = footnotes, navbar = page name }
year
- sets the Gregorian year to base calendar calculations on. If not specified, the current year is used.footnotes
- sets text to be displayed in a footnotes section at the bottom of the sidebar.navbar
- sets the page name to be used by the navbar.Calendar box objects have the following properties:
calendarBox.year
- the Gregorian year number. This is negative for BC years; for example, for the year 100 BC the value of calendarBox.year is -99
. (BC years are calculated by "1 - n" rather than "0 - n", as there is no year zero.)calendarBox.yearText
- the Gregorian year text. This is a string value of the format "n" for AD years and "n BC" for BC years.calendarBox.caption
- the text of the box caption (the bold text that appears directly above the box). The default caption is the value of calendarBox.yearText
.calendarBox.footnotes
- the text of the box footnotes.calendarBox.navbar
- the page name used by the navbar.Calendar box objects have the following methods:
calendarBox:setCaption( caption )
- sets the box caption (the bold text that appears directly above the box). The default caption is the value of calendarBox.yearText
.calendarBox:addCalendar( obj )
- adds a calendar object or a calendar group object to the calendar box.calendarBox:addCalendarGroup( obj )
- an alias for myCalendarBox:addCalendar()
.calendarBox:export()
- converts the calendar box object to wikicode. This calls calendar:export()
and calendarGroup:export()
to export calendar objects and calendar group objects.A calendar
object is initiated with:
local myCalendar = calendar:new()
Calendar objects have the following properties:
calendar.link
- the link name.calendar.year
- the year value. This is always a string value.Calendar objects have the following methods:
calendar:setLink( link, display )
- sets the link name for the calendar object. link
is the name of Wikipedia's article about the calendar, and display
is an optional display name for the article link.calendar:setRawLink( wikitext )
- sets the calendar link as raw wikitext.calendar:getLink()
- gets the link value.calendar:setYear( year )
- sets the year value for the calendar. year
can be a number or a string.calendar:setYearRange( startYear, endYear )
- sets the year value for the calendar as a year range. Both startYear
and endYear
must be number values.calendar:export()
- exports the calendar to wikitext. If no link value was found, this returns nil
. If a link was found but no year value was found, the calendar is output with a value of N/A
for the year.A calendarGroup
object is initiated with:
local myCalendarGroup = calendarGroup:new{ heading = heading }
heading
- the wikitext heading for the calendar group (e.g. [[Hindu calendar]]s
).Calendar group objects have one property:
calendarGroup.heading
- the calendar group heading text.Calendar group objects have the following methods:
calendarGroup:addCalendar( obj )
- adds a calendar object to the calendar group.calendarGroup:export()
- converts a calendar group to wikitext. Calls calendar:export()
to export individual calendar objects.
-- Load dependencies.
local htmlBuilder = require( 'Module:HtmlBuilder' )
local makeNavbar = require( 'Module:Navbar' ).navbar
local numToRoman = require( 'Module:Roman' ).main
local numToArmenian = require( 'Module:Armenian' ).main
local getRegnal = require( 'Module:British regnal year' ).main
local japaneseEra = require( 'Module:Japanese calendar' ).era
-- Define constants.
local lang = mw.language.getContentLanguage()
local currentYear = tonumber( lang:formatDate( 'Y' ) )
--------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------
local function isInteger( num )
num = tonumber( num )
if num and math.floor( num ) == num and num ~= math.huge then
return num
else
return false
end
end
-- Converts strings of the format "n BC" to their corresponding
-- numerical values.
local function BCToNum( s )
if type( s ) ~= 'string' then
return nil
end
s = mw.ustring.match( s, '^([1-9]%d*)%s*BC$' )
if not s then
return nil
end
local num = tonumber( s )
num = ( num - 1 ) * -1
return num
end
-- For BC years, returns a string with the year name appended with " BC".
-- Otherwise returns the year number.
local function numToBC( num )
if type( num ) ~= 'number' then
error( mw.ustring.format( 'Non-number input %s passed to numToBC', tostring( num ) ) )
end
if num <= 0 then
num = -1 * ( num - 1 )
local BCYear = mw.ustring.format( '%d BC', num )
return BCYear
else
return num
end
end
-- Gets the display text for a Gregorian year. If gregcal is specified, returns a wikilink.
local function getGregLink( year, gregcal )
year = tonumber( year )
if not year then return end
local yearName = tostring( numToBC( year ) )
if type( gregcal ) == 'string' and gregcal ~= '' then
return mw.ustring.format( '[[%s|%s]]', gregcal, yearName )
else
return tostring( yearName )
end
end
-- Get the year text for a Gregorian year. Used in both the Gregorian and Julian calendars.
local function getGregYearText( year, gregcal )
local link = getGregLink( year, gregcal )
local ret = htmlBuilder.create()
ret
.wikitext( link )
local romanYear = numToRoman{ year }
if romanYear then
ret
.tag( 'br', { selfClosing = true } )
.tag( 'span' )
.css( 'font-family', 'serif' )
.wikitext( mw.ustring.format( "''%s''", romanYear ) )
end
return tostring( ret )
end
--------------------------------------------------------------------
-- Calendar box class definition
--------------------------------------------------------------------
local calendarBox = {}
calendarBox.__index = calendarBox
function calendarBox:new( init )
init = type( init ) == 'table' and init or {}
local obj = {}
local pagename = 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.
local initYear = isInteger( init.year )
if initYear then
self.year = initYear
else
local BCYear = BCToNum( pagename )
if BCYear then
self.year = BCYear
else
local pagenameNum = isInteger( pagename )
if pagenameNum then
self.year = pagenameNum
else
self.year = currentYear
end
end
end
-- Set the caption.
local BCYearName = numToBC( self.year )
if type( BCYearName ) == 'string' then
self.caption = BCYearName
elseif type( BCYearName ) == 'number' then
self.caption = tostring( BCYearName )
else
error( mw.ustring.format( 'Invalid caption "%s" detected', tostring( BCYearName ) ) )
end
-- Set other fields.
self.footnotes = init.footnotes
self.navbar = init.navbar
return setmetatable( obj, {
__index = self
})
end
function calendarBox:addCalendar( obj )
if not ( type( obj ) == 'table' ) then
error( 'invalid calendar object "' .. obj .. '" passed to addCalendar' )
end
self.calendars = self.calendars or {}
table.insert( self.calendars, obj )
end
-- We add calendar groups in exactly the same way that we add calendars. It is the export()
-- function that does the work of figuring out which object is which type.
calendarBox.addCalendarGroup = calendarBox.addCalendar
function calendarBox:export()
local root = htmlBuilder.create( 'table' )
-- Export the calendar box headers.
root
.addClass( 'infobox' )
.addClass( 'vevent' )
.css( 'width', '22em' )
.tag( 'caption' )
.css( 'font-size', '125%' )
.tag( 'span' )
.addClass( 'summary' )
.addClass( 'dtstart' )
.wikitext( self.caption )
-- Define a function to export one calendar object.
local function exportCalendar( calendar, group )
if type( calendar ) ~= 'table' or not calendar.getLink or not calendar.calculateYear then return end
-- Process the link.
local link = calendar.getLink( self.year )
if type( link ) ~= 'string' then return end -- Exit if no link was specified, for example Unix times before 1970.
link = ( group and ' - ' or '' ) .. link
-- Process the year.
local yearText
local year1, year2 = calendar.calculateYear( self.year )
if year1 and year2 then
if type( year1 ) == 'number' and type( year2 ) == 'number' and ( year1 < 0 or year2 < 0 ) then -- Leave a gap for negative years to avoid having a minus sign and a dash right next to each other.
year1 = tostring( year1 ) .. ' '
year2 = ' ' .. tostring( year2 )
else
year1 = tostring( year1 )
year2 = tostring( year2 )
end
yearText = mw.ustring.format( '%s–%s', year1, year2 )
else
yearText = year1 and tostring( year1 ) or "''N/A''" -- Automatically return N/A if year1 returns nil or false.
end
-- Build the table row.
root
.tag( 'tr' )
.tag( 'td' )
.wikitext( link )
.done()
.tag( 'td' )
.wikitext( yearText )
.allDone()
end
-- Check whether the objects in self.calendars are calendar objects or calendar group objects,
-- and export them as appropriate.
for i, t in ipairs( self.calendars ) do
if type( t.calendars ) == 'table' then
-- We are dealing with a calendar group object.
if type( t.heading ) == 'string' then
-- Display the heading if it is present.
root
.tag( 'tr' )
.tag( 'td' )
.wikitext( t.heading )
.done()
.tag( 'td' ) -- Use a blank tag to make the html look nice.
.allDone()
end
for j, calendar in ipairs( t.calendars ) do
exportCalendar( calendar, true )
end
else
-- We are dealing with a calendar object.
exportCalendar( t )
end
end
-- Add footnotes.
if type( self.footnotes ) == 'string' then
root
.tag( 'tr' )
.tag( 'td' )
.attr( 'colspan', '2' )
.wikitext( mw.ustring.format( '<small>%s</small>', self.footnotes ) )
.allDone()
end
-- Add navbar.
if type( self.navbar ) == 'string' then
root
.tag( 'tr' )
.tag( 'td' )
.attr( 'colspan', '2' )
.css( 'text-align', 'center' )
.wikitext( makeNavbar{ self.navbar } )
.allDone()
end
return tostring( 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.
local calendarGroup = {}
calendarGroup.__index = calendarGroup
calendarGroup.type = 'calendarGroup'
function calendarGroup:new( init )
init = type( init ) == 'table' and init or {}
local obj = {}
obj.heading = init.heading
obj.calendars = {}
if type( init.calendars ) == 'table' then
for i, v in ipairs( init.calendars ) do
if type( v ) == 'table' then
table.insert( obj.calendars, v )
end
end
end
return setmetatable( obj, {
__index = self
})
end
function calendarGroup:addCalendar( calendar )
self.calendars = self.calendars or {}
if type( calendar ) == 'table' then
table.insert( self.calendars, calendar )
end
end
--------------------------------------------------------------------
-- Calendar class definition
--------------------------------------------------------------------
local calendar = {}
calendar.__index = calendar
calendar.type = 'calendar'
function calendar:new()
local obj = {}
return setmetatable( obj, {
__index = self
})
end
function calendar:setLink( link, display, italics )
if not type( link ) == 'string' then
return nil
end
display = type( display ) == 'string' and display
local ret
if display then
ret = mw.ustring.format( '[[%s|%s]]', link, display )
else
ret = mw.ustring.format( '[[%s]]', link )
end
if italics then
ret = mw.ustring.format( "''%s''", ret )
end
self.getLink = function()
return ret
end
end
function calendar:setLinkFunction( func )
self.getLink = func
end
-- This function sets the year. It can return one value for a single year, or
-- two values to specify a year range.
function calendar:setYearFunction( func )
self.calculateYear = func
end
--------------------------------------------------------------------
-- Build the box
--------------------------------------------------------------------
local function _main( args )
args.navbar = 'Year in other calendars'
local box = calendarBox:new( args )
-- Gregorian calendar
local gregorian = calendar:new()
gregorian:setLink( 'Gregorian calendar' )
gregorian:setYearFunction(
function( year )
return getGregYearText( year, args.gregcal )
end
)
box:addCalendar( gregorian )
-- Ab urbe condita
local abUrbe = calendar:new()
abUrbe:setLink( 'Ab urbe condita' )
abUrbe:setYearFunction(
function( year )
return year + 753
end
)
box:addCalendar( abUrbe )
-- Armenian calendar
local armenian = calendar:new()
armenian:setLink( 'Armenian calendar' )
armenian:setYearFunction(
function( year )
if year - 550 > 0 then
local armenianYear = year - 551
return mw.ustring.format( '%s<br />ԹՎ %s', armenianYear, numToArmenian( armenianYear ) )
end
end
)
box:addCalendar( armenian )
-- Assyrian calendar
local assyrian = calendar:new()
assyrian:setLink( 'Assyrian calendar' )
assyrian:setYearFunction(
function( year )
return year + 4750
end
)
box:addCalendar( assyrian )
-- Bahá'í calendar
local bahai = calendar:new()
bahai:setLink( "Bahá'í calendar" )
bahai:setYearFunction(
function( year )
return year - 1844, year - 1843
end
)
box:addCalendar( bahai )
-- Bengali calendar
local bengali = calendar:new()
bengali:setLink( 'Bengali calendar' )
bengali:setYearFunction(
function( year )
return year - 593
end
)
box:addCalendar( bengali )
-- Berber calendar
local berber = calendar:new()
berber:setLink( 'Berber calendar' )
berber:setYearFunction(
function( year )
return year + 950
end
)
box:addCalendar( berber )
-- Regnal year
local regnal = calendar:new()
regnal:setLinkFunction(
function( year )
local regnalName
if year > 1706 then
regnalName = 'British'
else
regnalName = 'English'
end
return mw.ustring.format( '[[Regnal years of English monarchs|%s Regnal year]]', regnalName )
end
)
regnal:setYearFunction(
function( year )
return getRegnal( year )
end
)
box:addCalendar( regnal )
-- Buddhist calendar
local buddhist = calendar:new()
buddhist:setLink( 'Buddhist calendar' )
buddhist:setYearFunction(
function( year )
return year + 544
end
)
box:addCalendar( buddhist )
-- Burmese calendar
local burmese = calendar:new()
burmese:setLink( 'Traditional Burmese calendar', 'Burmese calendar' )
burmese:setYearFunction(
function( year )
return year - 638
end
)
box:addCalendar( burmese )
-- Byzantine calendar
local byzantine = calendar:new()
byzantine:setLink( 'Byzantine calendar' )
byzantine:setYearFunction(
function( year )
return year + 5508, year + 5509
end
)
box:addCalendar( byzantine )
-- Chinese calendar
local chinese = calendar:new()
chinese:setLink( 'Chinese calendar' )
chinese:setYearFunction(
function( year )
-- Define the information for the "heavenly stems" and "earthly branches" year cycles.
-- See [[Chinese calendar#Cycle of years]] for information.
local heavenlyStems = {
{ '甲', 'Wood' }, -- 1
{ '乙', 'Wood' }, -- 2
{ '丙', 'Fire' }, -- 3
{ '丁', 'Fire' }, -- 4
{ '戊', 'Earth' }, -- 5
{ '己', 'Earth' }, -- 6
{ '庚', 'Metal' }, -- 7
{ '辛', 'Metal' }, -- 8
{ '壬', 'Water' }, -- 9
{ '癸', 'Water' } -- 10
}
local earthlyBranches = {
{ '子', '[[Rat (zodiac)|Rat]]' }, -- 1
{ '丑', '[[Ox (zodiac)|Ox]]' }, -- 2
{ '寅', '[[Tiger (zodiac)|Tiger]]' }, -- 3
{ '卯', '[[Rabbit (zodiac)|Rabbit]]' }, -- 4
{ '辰', '[[Dragon (zodiac)|Dragon]]' }, -- 5
{ '巳', '[[Snake (zodiac)|Snake]]' }, -- 6
{ '午', '[[Horse (zodiac)|Horse]]' }, -- 7
{ '未', '[[Goat (zodiac)|Goat]]' }, -- 8
{ '申', '[[Monkey (zodiac)|Monkey]]' }, -- 9
{ '酉', '[[Rooster (zodiac)|Rooster]]' }, -- 10
{ '戌', '[[Dog (zodiac)|Dog]]' }, -- 11
{ '亥', '[[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.
local sexagenaryYear1 = ( year - 4 ) % 60
local sexagenaryYear2 = ( year - 3 ) % 60
local heavenlyNum1 = sexagenaryYear1 % 10
local heavenlyNum2 = sexagenaryYear2 % 10
local earthlyNum1 = sexagenaryYear1 % 12
local earthlyNum2 = sexagenaryYear2 % 12
-- If the value is 0 increase it by one cycle so that we can use it with Lua arrays.
if heavenlyNum1 == 0 then
heavenlyNum1 = 10
end
if heavenlyNum2 == 0 then
heavenlyNum2 = 10
end
if earthlyNum1 == 0 then
earthlyNum1 = 12
end
if earthlyNum2 == 0 then
earthlyNum2 = 12
end
-- Get the data tables for each permutation.
local heavenlyTable1 = heavenlyStems[ heavenlyNum1 ]
local heavenlyTable2 = heavenlyStems[ heavenlyNum2 ]
local earthlyTable1 = earthlyBranches[ earthlyNum1 ]
local earthlyTable2 = earthlyBranches[ earthlyNum2 ]
-- Work out the continously-numbered year. (See [[Chinese calendar#Continuously numbered years]].)
local year1 = year + 2696
local year2 = year + 2697
local year1Alt = year1 - 60
local year2Alt = year2 - 60
-- Return all of that data in a (hopefully) reader-friendly format.
return mw.ustring.format(
"[[Sexagenary cycle|%s%s]]年 (%s %s)<br />%d or %d<br /> ''— to —''<br />%s%s年 (%s %s)<br />%d or %d",
heavenlyTable1[ 1 ],
earthlyTable1[ 1 ],
heavenlyTable1[ 2 ],
earthlyTable1[ 2 ],
year1,
year1Alt,
heavenlyTable2[ 1 ],
earthlyTable2[ 1 ],
heavenlyTable2[ 2 ],
earthlyTable2[ 2 ],
year2,
year2Alt
)
end
)
box:addCalendar( chinese )
-- Coptic calendar
local coptic = calendar:new()
coptic:setLink( 'Coptic calendar' )
coptic:setYearFunction(
function( year )
return year - 284, year - 283
end
)
box:addCalendar( coptic )
-- Ethiopian calendar
local ethiopian = calendar:new()
ethiopian:setLink( 'Ethiopian calendar' )
ethiopian:setYearFunction(
function( year )
return year - 8, year - 7
end
)
box:addCalendar( ethiopian )
-- Hebrew calendar
local hebrew = calendar:new()
hebrew:setLink( 'Hebrew calendar' )
hebrew:setYearFunction(
function( year )
return year + 3760, year + 3761
end
)
box:addCalendar( hebrew )
-- Hindu calendars
local hindu = calendarGroup:new{ heading = '[[Hindu calendar]]s' }
-- Vikram Samvat
local vikramSamvat = calendar:new()
vikramSamvat:setLink( 'Vikram Samvat', false, true ) -- use italics
vikramSamvat:setYearFunction(
function( year )
return year + 56, year + 57
end
)
hindu:addCalendar( vikramSamvat )
-- Shaka Samvat
local shakaSamvat = calendar:new()
shakaSamvat:setLink( 'Indian national calendar', 'Shaka Samvat', true ) -- display "Shaka Samvat" and use italics
shakaSamvat:setYearFunction(
function( year )
if year - 76 > 0 then
return year - 78, year - 77
end
end
)
hindu:addCalendar( shakaSamvat )
-- Kali Yuga
local kaliYuga = calendar:new()
kaliYuga:setLink( 'Kali Yuga', false, true ) -- use italics
kaliYuga:setYearFunction(
function( year )
return year + 3101, year + 3102
end
)
hindu:addCalendar( kaliYuga )
box:addCalendarGroup( hindu )
-- Holocene calendar
local holocene = calendar:new()
holocene:setLink( 'Human Era', 'Holocene calendar' )
holocene:setYearFunction(
function( year )
return year + 10000
end
)
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.
local igbo = calendar:new()
igbo:setLink( 'Igbo calendar' )
igbo:setYearFunction(
function( year )
return year - 1000, year - 999
end
)
box:addCalendar( igbo )
-- Iranian calendar
local iranian = calendar:new()
iranian:setLink( 'Iranian calendars', 'Iranian calendar' )
iranian:setYearFunction(
function( year )
if year - 621 > 0 then
return mw.ustring.format( '%d–%d', year - 622, year - 621 )
else
return mw.ustring.format( '%d BP – %d BP', -(year - 622), -(year - 621) )
end
end
)
box:addCalendar( iranian )
-- Islamic calendar
local islamic = calendar:new()
islamic:setLink( 'Islamic calendar' )
islamic:setYearFunction(
function( year )
local mult = 1.030684 -- the factor to multiply by
local sub = 621.5643 -- the factor to subtract by
if year - 621 > 0 then
local year1 = math.floor( mult * ( year - sub ) )
local year2 = math.floor( mult * ( year - sub + 1 ) )
return mw.ustring.format( '%d–%d', year1, year2 )
else
local year1 = math.ceil( -mult * ( year - sub ) )
local year2 = math.ceil( -mult * ( year - sub + 1 ) )
return mw.ustring.format( '%d BH – %d BH', year1, year2 )
end
end
)
box:addCalendar( islamic )
-- Japanese calendar
local japanese = calendar:new()
japanese:setLink( 'Japanese calendar' )
japanese:setYearFunction(
function( year )
local thisEra = japaneseEra:new{ year = year }
if not thisEra then return end
local ret = {}
local oldEra = thisEra:getOldEra()
if oldEra and oldEra.eraYear and thisEra.article ~= oldEra.article then
local oldText = mw.ustring.format( '%s %d', oldEra.link, oldEra.eraYear )
table.insert( ret, oldText )
table.insert( ret, ' / ' )
end
if thisEra.eraYear then
table.insert( ret, mw.ustring.format( '%s %d', thisEra.link, thisEra.eraYear ) )
end
table.insert( ret, mw.ustring.format( '<br /><small>(%s%s年)</small>', thisEra.kanji, thisEra.eraYearKanji ) )
return table.concat( ret )
end
)
box:addCalendar( japanese )
-- Juche calendar
local juche = calendar:new()
juche:setLink( 'North Korean calendar', 'Juche calendar' )
juche:setYearFunction(
function( year )
if year > 1911 then
return year - 1911
end
end
)
box:addCalendar( juche )
-- Julian calendar
local julian = calendar:new()
julian:setLink( 'Julian calendar' )
julian:setYearFunction(
function( year )
local yearFuncs = {
{ 1901, function() return 'Gregorian minus 13 days' end },
{ 1900, function() return 'Gregorian minus 12 or 13 days' end },
{ 1801, function() return 'Gregorian minus 12 days' end },
{ 1800, function() return 'Gregorian minus 11 or 12 days' end },
{ 1701, function() return 'Gregorian minus 11 days' end },
{ 1700, function() return 'Gregorian minus 10 or 11 days' end },
{ 1582, function() return 'Gregorian minus 10 days' end },
{ -45, function( year ) return getGregYearText( year, args.gregcal ) end }
}
for i, t in ipairs( yearFuncs ) do
if year >= t[ 1 ] then
return t[ 2 ]( year )
end
end
end
)
box:addCalendar( julian )
-- Korean calendar
local korean = calendar:new()
korean:setLink( 'Korean calendar' )
korean:setYearFunction(
function( year )
return year + 2333
end
)
box:addCalendar( korean )
-- Minguo calendar
local minguo = calendar:new()
minguo:setLink( 'Minguo calendar' )
minguo:setYearFunction(
function( year )
if year > 1911 then
year = year - 1911
return mw.ustring.format( '[[Taiwan|ROC]] %d<br /><small>民國%d年</small>', year, year )
else
year = 1911 - year + 1
return mw.ustring.format( '%d before [[Republic of China|ROC]]<br /><small>民前%d年</small>', year, year )
end
end
)
box:addCalendar( minguo )
-- Thai solar calendar
local thai = calendar:new()
thai:setLink( 'Thai solar calendar' )
thai:setYearFunction(
function( year )
return year + 543
end
)
box:addCalendar( thai )
-- Unix time
local function getUnixTime( year )
if year < 1970 then return end
local noError, unixTime = pcall( lang.formatDate, lang, 'U', '1 Jan ' .. tostring( year ) )
if not noError or noError and not unixTime then return end
unixTime = tonumber( unixTime )
if unixTime and unixTime >= 0 then
return unixTime
end
end
local unix = calendar:new()
unix:setLinkFunction(
function( year )
local unixTimeThis = getUnixTime( year )
local unixTimeNext = getUnixTime( year + 1 )
if unixTimeThis and unixTimeNext then
return '[[Unix time]]'
end
end
)
unix:setYearFunction(
function( year )
local unixTimeThis = tonumber( getUnixTime( year ) )
local unixTimeNext = tonumber( getUnixTime( year + 1 ) )
if unixTimeThis and unixTimeNext then
return unixTimeThis, unixTimeNext - 1
end
end
)
box:addCalendar( unix )
return box:export()
end
--------------------------------------------------------------------
-- Output the box and the class definitions
--------------------------------------------------------------------
local p = {}
function p.main( frame )
-- If called via #invoke, use the args passed into the invoking
-- template, or the args passed to #invoke if any exist. Otherwise
-- assume args are being passed directly in from the debug console
-- or from another Lua module.
local origArgs
if frame == mw.getCurrentFrame() then
origArgs = frame:getParent().args
for k, v in pairs( frame.args ) do
origArgs = frame.args
break
end
else
origArgs = frame
end
-- Trim whitespace and remove blank arguments.
local args = {}
for k, v in pairs( origArgs ) do
if type( v ) == 'string' then
v = mw.text.trim( v )
end
if v ~= '' then
args[k] = v
end
end
return _main( args )
end
p.calendarBox = calendarBox
p.calendarGroup = calendarGroup
p.calendar = calendar
return p