Module:Year in various calendars/sandbox
![]() | This is the module sandbox page for Module:Year in various calendars (diff). |
![]() | This Lua module is used on approximately 2,700 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 is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
![]() | This module depends on the following other modules: |
This module produces the sidebar opposite displaying a given Gregorian year in various different calendars.
Syntax
Simple
{{#invoke:Year in various calendars|main}}
All parameters
{{#invoke:Year in various calendars|main |year=(n) |footnotes=(footnotes) |gregcal=(article name)}}
Parameters
- year
- Number specifying the year to be displayed. This can be negative and also can be in the format "n BC" to display BC dates or "AD n" as an alternative to a positive number. If not specified, the current year is used.
- footnotes
- Any footnotes to be placed at the bottom of the sidebar.
- gregcal
- Name of an article to be displayed for Gregorian and Julian years (e.g. "2000 BC"). Do not include square brackets.
Microformat
- Classes used
The HTML classes of this microformat include:
- attendee
- description
- dtend
- dtstart
- location
- summary
- url
- vevent
nor collapse nested elements which use them.
Adding new calendars
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()
.
Technical details
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
calendarBox class
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 ofcalendarBox.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 ofcalendarBox.yearText
.calendarBox:addCalendar( obj )
- adds a calendar object or a calendar group object to the calendar box.calendarBox:addCalendarGroup( obj )
- an alias formyCalendarBox:addCalendar()
.calendarBox:export()
- converts the calendar box object to wikicode. This callscalendar:export()
andcalendarGroup:export()
to export calendar objects and calendar group objects.
calendar class
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, anddisplay
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. BothstartYear
andendYear
must be number values.calendar:export()
- exports the calendar to wikitext. If no link value was found, this returnsnil
. If a link was found but no year value was found, the calendar is output with a value ofN/A
for the year.
calendarGroup class
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. Callscalendar:export()
to export individual calendar objects.
See also
local dts = require( 'Module:User:Anomie/deepToString' ).deepToString -- for debugging
-- 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( mw.ustring.upper( 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 nil.
local function numToBC( num )
num = isInteger( num )
if not num then return end
if num <= 0 then
return mw.ustring.format( '%d BC', 1 - num )
end
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 yearNum = isInteger( init.year )
if yearNum then -- First, see if the year parameter is a number.
self.year = yearNum
else
local yearBC = BCToNum( init.year )
if yearBC then -- Second, see if the year parameter is a "yyyy BC" string.
self.year = yearBC
else
local pageNum = isInteger( pagename )
if pageNum then -- Third, see if the pagename is an integer.
self.year = pageNum
else
local pageBC = BCToNum( pagename )
if pageBC then -- Fourth, see if the pagename is a "yyyy BC" string.
self.year = pageBC
else
self.year = currentYear -- If none of the above apply, use the current year.
end
end
end
end
-- Set year text values.
self.BCYearName = numToBC( self.year )
if self.BCYearName then
self.yearText = self.BCYearName
else
self.yearText = tostring( self.year )
end
-- Set other fields.
self.caption = self.yearText
self.footnotes = init.footnotes
self.navbar = init.navbar
return setmetatable( obj, {
__index = self
})
end
-- Sets the calendar box caption.
function calendarBox:setCaption( s )
if type( s ) ~= 'string' or s == '' then return end
self.caption = s
end
-- Adds a calendar or a calendar group.
function calendarBox:addCalendar( obj )
if type( obj ) ~= 'table' and type( obj.new ) ~= 'function' then return end -- Exit if the object is invalid.
self.calendars = self.calendars or {}
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
-- Outputs the calendar box wikitext.
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 )
-- 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.
if type( self.calendars ) == 'table' then
for i, calendar in ipairs( self.calendars ) do
local calendarText = calendar:export()
if type( calendarText ) == 'string' then
root.wikitext( calendarText )
end
end
end
-- Add footnotes.
if type( self.footnotes ) == 'string' and self.footnotes ~= '' then
root
.tag( 'tr' )
.tag( 'td' )
.attr( 'colspan', '2' )
.wikitext( mw.ustring.format( '<small>%s</small>', self.footnotes ) )
end
-- Add navbar.
if type( self.navbar ) == 'string' and self.navbar ~= '' then
root
.tag( 'tr' )
.tag( 'td' )
.attr( 'colspan', '2' )
.css( 'text-align', 'center' )
.wikitext( makeNavbar{ self.navbar } )
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
function calendarGroup:new( init )
init = type( init ) == 'table' and init or {}
local obj = {}
-- Get the heading and throw an error if it is invalid.
obj.heading = init.heading
if type( obj.heading ) ~= 'string' then
error( 'calendarGroup: no heading detected' )
end
-- Set the metatable and return the object.
self.__index = self
return setmetatable( obj, {
__index = self
})
end
-- Adds a calendar object to the calendar group.
function calendarGroup:addCalendar( calendar )
self.calendars = self.calendars or {}
if type( calendar ) == 'table' and type( calendar.getLink ) == 'function' then
table.insert( self.calendars, calendar )
end
end
-- Exports the calendar group's wikitext.
function calendarGroup:export()
-- Indent and italicise each calendar's link if it exists.
for i, calendar in ipairs( self.calendars ) do
local link = calendar:getLink()
if type( link ) == 'string' then
self.calendars[ i ]:setRawLink( mw.ustring.format( " - ''%s''", link ) )
end
end
-- Create the heading row html and export the calendar objects.
local ret = htmlBuilder.create()
ret
.tag( 'tr' )
.tag( 'td' )
.wikitext( self.heading )
.done()
.tag( 'td' ) -- Use a blank tag to make the html look nice.
.allDone()
for i, calendar in ipairs( self.calendars ) do
ret.wikitext( calendar:export() )
end
return tostring( ret )
end
--------------------------------------------------------------------
-- Calendar class definition
--------------------------------------------------------------------
local calendar = {}
calendar.__index = calendar
calendar.type = 'calendar'
function calendar:new()
local obj = {}
return setmetatable( obj, {
__index = self
})
end
-- Sets the calendar's wikilink, with optional display text and italics.
function calendar:setLink( link, display )
if type( link ) ~= 'string' or link == '' then return end
display = type( display ) == 'string' and display ~= '' and display
if display then
self.link = mw.ustring.format( '[[%s|%s]]', link, display )
else
self.link = mw.ustring.format( '[[%s]]', link )
end
end
-- Sets the calendar's wikilink as raw wikitext.
function calendar:setRawLink( s )
if type( s ) ~= 'string' or s == '' then return end
self.link = s
end
-- Returns the calendar's link value.
function calendar:getLink()
return self.link
end
-- Sets a single year. Can be passed either a string or a number.
function calendar:setYear( year )
if type( year ) == 'number' then
self.year = tostring( year )
elseif type( year ) == 'string' then
self.year = year
end
end
-- Sets a year range. Must be passed two numbers.
function calendar:setYearRange( year1, year2 )
if type( year1 ) == 'number' and type( year2 ) == 'number' then
if 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.
self.year = mw.ustring.format( '%d – %d', year1, year2 )
else
self.year = mw.ustring.format( '%d–%d', year1, year2 )
end
end
end
-- Outputs the calendar wikitext.
function calendar:export()
-- Exit if no link has been specified.
local link = self.link
if type( link ) ~= 'string' or link == '' then return end
-- If no year has been specified, set the year value to N/A.
local year = self.year
if type( year ) ~= 'string' or year == '' then
year = "''N/A''"
end
-- Build the table row.
local ret = htmlBuilder.create()
ret
.tag( 'tr' )
.tag( 'td' )
.wikitext( link )
.done()
.tag( 'td' )
.wikitext( year )
.allDone()
return tostring( ret )
end
--------------------------------------------------------------------
-- Build the box
--------------------------------------------------------------------
local function makeCalendarBox( args )
-- Initiate the box and get the year values.
local init = args
init.navbar = 'Year in other calendars'
local box = calendarBox:new( init )
local year = box.year
local yearText = box.yearText
-- Set the caption.
box:setCaption( box.caption .. ' in other calendars' )
----------------------------------------------------------------------
-- Gregorian calendar
----------------------------------------------------------------------
local gregorian = calendar:new()
gregorian:setLink( 'Gregorian calendar' )
-- Get the year link.
local gregcal = args.gregcal
if type( gregcal ) == 'string' and gregcal ~= '' then
gregorian.yearLink = mw.ustring.format( '[[%s|%s]]', gregcal, yearText )
else
gregorian.yearLink = yearText
end
-- Set the year.
gregorian.romanYear = numToRoman{ year }
if gregorian.romanYear then
gregorian:setYear( mw.ustring.format(
[[%s<br /><span style="font-family: serif;">''%s''</span>]],
gregorian.yearLink, gregorian.romanYear
) )
else
gregorian:setYear( gregorian.yearLink )
end
box:addCalendar( gregorian )
----------------------------------------------------------------------
-- Ab urbe condita
----------------------------------------------------------------------
local abUrbe = calendar:new()
abUrbe:setLink( 'Ab urbe condita' )
abUrbe:setYear( year + 753 )
box:addCalendar( abUrbe )
----------------------------------------------------------------------
-- Armenian calendar
----------------------------------------------------------------------
local armenian = calendar:new()
armenian:setLink( 'Armenian calendar' )
if year > 550 then
local armenianYear = year - 551
armenian:setYear( mw.ustring.format( '%s<br />ԹՎ %s', armenianYear, numToArmenian( armenianYear ) ) )
end
box:addCalendar( armenian )
----------------------------------------------------------------------
-- Assyrian calendar
----------------------------------------------------------------------
local assyrian = calendar:new()
assyrian:setLink( 'Assyrian calendar' )
assyrian:setYear( year + 4750 )
box:addCalendar( assyrian )
----------------------------------------------------------------------
-- Bahá'í calendar
----------------------------------------------------------------------
local bahai = calendar:new()
bahai:setLink( "Bahá'í calendar" )
bahai:setYearRange( year - 1844, year - 1843 )
box:addCalendar( bahai )
----------------------------------------------------------------------
-- Bengali calendar
----------------------------------------------------------------------
local bengali = calendar:new()
bengali:setLink( 'Bengali calendar' )
bengali:setYear( year - 593 )
box:addCalendar( bengali )
----------------------------------------------------------------------
-- Berber calendar
----------------------------------------------------------------------
local berber = calendar:new()
berber:setLink( 'Berber calendar' )
berber:setYear( year + 950 )
box:addCalendar( berber )
----------------------------------------------------------------------
-- Regnal year
----------------------------------------------------------------------
local regnal = calendar:new()
local regnalName
if year > 1706 then
regnalName = 'British'
else
regnalName = 'English'
end
regnal:setLink( 'Regnal years of English monarchs', regnalName .. ' Regnal year' )
regnal:setYear( getRegnal( year ) )
box:addCalendar( regnal )
----------------------------------------------------------------------
-- Buddhist calendar
----------------------------------------------------------------------
local buddhist = calendar:new()
buddhist:setLink( 'Buddhist calendar' )
buddhist:setYear( year + 544 )
box:addCalendar( buddhist )
----------------------------------------------------------------------
-- Burmese calendar
----------------------------------------------------------------------
local burmese = calendar:new()
burmese:setLink( 'Traditional Burmese calendar', 'Burmese calendar' )
burmese:setYear( year - 638 )
box:addCalendar( burmese )
----------------------------------------------------------------------
-- Byzantine calendar
----------------------------------------------------------------------
local byzantine = calendar:new()
byzantine:setLink( 'Byzantine calendar' )
byzantine:setYearRange( year + 5508, year + 5509 )
box:addCalendar( byzantine )
----------------------------------------------------------------------
-- Chinese calendar
----------------------------------------------------------------------
local chinese = 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.
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.
chinese:setYear( mw.ustring.format(
[=[[[Sexagenary cycle|%s%s]]年 <small>(%s %s)</small><br />%d or %d<br /> ''— to —''<br />%s%s年 <small>(%s %s)</small><br />%d or %d]=],
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
----------------------------------------------------------------------
local coptic = calendar:new()
coptic:setLink( 'Coptic calendar' )
coptic:setYearRange( year - 284, year - 283 )
box:addCalendar( coptic )
----------------------------------------------------------------------
-- Ethiopian calendar
----------------------------------------------------------------------
local ethiopian = calendar:new()
ethiopian:setLink( 'Ethiopian calendar' )
ethiopian:setYearRange( year - 8, year - 7 )
box:addCalendar( ethiopian )
----------------------------------------------------------------------
-- Hebrew calendar
----------------------------------------------------------------------
local hebrew = calendar:new()
hebrew:setLink( 'Hebrew calendar' )
hebrew:setYearRange( year + 3760, year + 3761 )
box:addCalendar( hebrew )
----------------------------------------------------------------------
-- Hindu calendars
----------------------------------------------------------------------
local hindu = calendarGroup:new{ heading = '[[Hindu calendar]]s' }
-- Vikram Samvat
local vikramSamvat = calendar:new()
vikramSamvat:setLink( 'Vikram Samvat' )
vikramSamvat:setYearRange( year + 56, year + 57 )
hindu:addCalendar( vikramSamvat )
-- Shaka Samvat
local shakaSamvat = calendar:new()
shakaSamvat:setLink( 'Indian national calendar', 'Shaka Samvat' )
if year - 76 > 0 then
shakaSamvat:setYearRange( year - 78, year - 77 )
end
hindu:addCalendar( shakaSamvat )
-- Kali Yuga
local kaliYuga = calendar:new()
kaliYuga:setLink( 'Kali Yuga' ) -- use italics
kaliYuga:setYearRange( year + 3101, year + 3102 )
hindu:addCalendar( kaliYuga )
box:addCalendarGroup( hindu )
----------------------------------------------------------------------
-- Holocene calendar
----------------------------------------------------------------------
local holocene = calendar:new()
holocene:setLink( 'Human Era', '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.
local igbo = calendar:new()
igbo:setLink( 'Igbo calendar' )
igbo:setYearRange( year - 1000, year - 999 )
box:addCalendar( igbo )
----------------------------------------------------------------------
-- Iranian calendar
----------------------------------------------------------------------
local iranian = calendar:new()
iranian:setLink( 'Iranian calendars', 'Iranian calendar' )
if year - 621 > 0 then
iranian:setYearRange( year - 622, year - 621 )
else
iranian:setYear( mw.ustring.format( '%d BP – %d BP', 622 - year, 621 - year ) )
end
box:addCalendar( iranian )
----------------------------------------------------------------------
-- Islamic calendar
----------------------------------------------------------------------
local islamic = calendar:new()
islamic:setLink( 'Islamic calendar' )
local islamicMult = 1.030684 -- the factor to multiply by
local islamicSub = 621.5643 -- the factor to subtract by
if year - 621 > 0 then
local year1 = math.floor( islamicMult * ( year - islamicSub ) )
local year2 = math.floor( islamicMult * ( year - islamicSub + 1 ) )
islamic:setYearRange( year1, year2 )
else
local year1 = math.ceil( -islamicMult * ( year - islamicSub ) )
local year2 = math.ceil( -islamicMult * ( year - islamicSub + 1 ) )
islamic:setYear( mw.ustring.format( '%d BH – %d BH', year1, year2 ) )
end
box:addCalendar( islamic )
----------------------------------------------------------------------
-- Japanese calendar
----------------------------------------------------------------------
local japanese = calendar:new()
japanese:setLink( 'Japanese calendar' )
japanese.thisEra = japaneseEra:new{ year = year }
if japanese.thisEra then
local japaneseYearText = {}
japanese.oldEra = japanese.thisEra:getOldEra()
if japanese.oldEra and japanese.oldEra.eraYear and japanese.thisEra.article ~= japanese.oldEra.article then
japanese.oldText = mw.ustring.format( '%s %d', japanese.oldEra.link, japanese.oldEra.eraYear )
table.insert( japaneseYearText, japanese.oldText )
table.insert( japaneseYearText, ' / ' )
end
if japanese.thisEra.eraYear then
table.insert( japaneseYearText, mw.ustring.format( '%s %d', japanese.thisEra.link, japanese.thisEra.eraYear ) )
end
table.insert( japaneseYearText, mw.ustring.format( '<br /><small>(%s%s年)</small>', japanese.thisEra.kanji, japanese.thisEra.eraYearKanji ) )
japanese:setYear( table.concat( japaneseYearText ) )
end
box:addCalendar( japanese )
----------------------------------------------------------------------
-- Juche calendar
----------------------------------------------------------------------
local juche = calendar:new()
juche:setLink( 'North Korean calendar', 'Juche calendar' )
if year > 1911 then
juche:setYear( year - 1911 )
end
box:addCalendar( juche )
----------------------------------------------------------------------
-- Julian calendar
----------------------------------------------------------------------
local julian = calendar:new()
julian:setLink( 'Julian calendar' )
julian.yearVals = {
{ 1901, 'Gregorian minus 13 days' },
{ 1900, 'Gregorian minus 12 or 13 days'},
{ 1801, 'Gregorian minus 12 days' },
{ 1800, 'Gregorian minus 11 or 12 days' },
{ 1701, 'Gregorian minus 11 days' },
{ 1700, 'Gregorian minus 10 or 11 days' },
{ 1582, 'Gregorian minus 10 days' },
{ -45, gregorian.year }
}
for i, t in ipairs( julian.yearVals ) do
if year >= t[ 1 ] then
julian:setYear( t[ 2 ] )
break
end
end
box:addCalendar( julian )
----------------------------------------------------------------------
-- Korean calendar
----------------------------------------------------------------------
local korean = calendar:new()
korean:setLink( 'Korean calendar' )
korean:setYear( year + 2333 )
box:addCalendar( korean )
----------------------------------------------------------------------
-- Minguo calendar
----------------------------------------------------------------------
local minguo = calendar:new()
minguo:setLink( 'Minguo calendar' )
if year > 1911 then
local minguoYear = year - 1911
minguo:setYear( mw.ustring.format( '[[Taiwan|ROC]] %d<br /><small>民國%d年</small>', minguoYear, minguoYear ) )
else
local minguoYear = 1911 - year + 1
minguo:setYear( mw.ustring.format( '%d before [[Republic of China|ROC]]<br /><small>民前%d年</small>', minguoYear, minguoYear ) )
end
box:addCalendar( minguo )
----------------------------------------------------------------------
-- Thai solar calendar
----------------------------------------------------------------------
local thai = calendar:new()
thai:setLink( 'Thai solar calendar' )
thai:setYear( year + 543 )
box:addCalendar( thai )
----------------------------------------------------------------------
-- Unix time
----------------------------------------------------------------------
local unix = calendar:new()
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
unix.thisYear = getUnixTime( year )
unix.nextYear = getUnixTime( year + 1 )
if unix.thisYear and unix.nextYear then
unix:setLink( 'Unix time' )
unix:setYearRange( unix.thisYear, unix.nextYear - 1 )
end
box:addCalendar( unix )
return box:export()
end
--------------------------------------------------------------------
-- Define functions and objects to make available externally
--------------------------------------------------------------------
local p = {}
-- Process the arguments and pass them to the box-building function.
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 makeCalendarBox( args )
end
p.calendarBox = calendarBox
p.calendarGroup = calendarGroup
p.calendar = calendar
return p