Module:Japanese calendar

From blackwiki
Revision as of 07:34, 22 August 2013 by blackwiki>Mr. Stradivarius (allow getting the era year for the first year of the next era (e.g. Taisho 14 is also Showa 1 ))
Jump to navigation Jump to search

This module is used to calculate dates in the Japanese calendar. It defines an "era" class which is designed to be called from other Lua modules, and it also contains several functions to export Japanese calendar data directly to Wikipedia pages through #invoke.

Usage

Through #invoke

{{#invoke:Japanese calendar|function_name|year=year|era=article name or kanji|previous=yes|next=yes}}

The function name specifies how the data should be outputted. The year and era parameters determine what era and year the module outputs. The next and previous parameters tell the module to return data for the next or previous era, rather than the one specified. If a combination of parameters is invalid the module will usually output nothing. However, if both the next and previous parameters are specified it will output an error.

Year and era

The year parameter is the year in the Gregorian calendar. The era parameter can either be the article name for that era, or the era's name in kanji. (Transcribed English era names can usually be used, but will not work if they are ambiguous.) Either year or era must be specified. If both are specified, the module defaults to using era to get the era data. This enables output of the last year of the previous era (for example, Shōwa 64 is the same year as Heisei 1).

Code Output
{{#invoke:Japanese calendar|link|year=1950}} Script error: The function "link" does not exist.
{{#invoke:Japanese calendar|link|era=Shōwa period}} Script error: The function "link" does not exist.
{{#invoke:Japanese calendar|link|era=昭和}} Script error: The function "link" does not exist.
{{#invoke:Japanese calendar|link|era=Shōwa}} Script error: The function "link" does not exist.
{{#invoke:Japanese calendar|link_year|year=1989}} Script error: The function "link_year" does not exist.
{{#invoke:Japanese calendar|link_year|year=1989|era=Shōwa period}} Script error: The function "link_year" does not exist.
{{#invoke:Japanese calendar|link_year|year=1990}} Script error: The function "link_year" does not exist.
{{#invoke:Japanese calendar|link_year|year=1990|era=Shōwa period}} Script error: The function "link_year" does not exist.
Functions
Code Description Example
baseyear The first year of the specified era. {{#invoke:Japanese calendar|baseyear|era=Heisei}}Script error: The function "baseyear" does not exist.
endyear The last year of the specified era. {{#invoke:Japanese calendar|endyear|era=Shōwa period}}Script error: The function "endyear" does not exist.
year The year for the specified era, without the era name. Defaults to the newer era, if more than one is applicable. {{#invoke:Japanese calendar|year|year=1989}}Script error: The function "year" does not exist.
kanjiyear The same as year, but in kanji. The first year of an era is changed to the kanji 元, and the others are changed to full-width numbers. {{#invoke:Japanese calendar|kanjiyear|year=1989}}Script error: The function "kanjiyear" does not exist.
article The Wikipedia article for the era, unlinked. {{#invoke:Japanese calendar|article|year=1950}}Script error: The function "article" does not exist.
label The name of the era. Same as article for undisambiguated titles. {{#invoke:Japanese calendar|label|year=1950}}Script error: The function "label" does not exist.
link A link to the Wikipedia article of the specified era. {{#invoke:Japanese calendar|link|year=1950}}Script error: The function "link" does not exist.
kanji The kanji for the specified era. {{#invoke:Japanese calendar|kanji|year=1950}}Script error: The function "kanji" does not exist.
label_year label followed by year {{#invoke:Japanese calendar|label_year|year=1989}}Script error: The function "label_year" does not exist.
link_year link followed by year {{#invoke:Japanese calendar|link_year|year=1989}}Script error: The function "link_year" does not exist.
label_kanjiyear label followed by kanjiyear {{#invoke:Japanese calendar|label_kanjiyear|year=1989}}Script error: The function "label_kanjiyear" does not exist.
link_kanjiyear link followed by kanjiyear {{#invoke:Japanese calendar|link_kanjiyear|year=1989}}Script error: The function "link_kanjiyear" does not exist.
Next, previous and old

If the next parameter is specified, the module outputs the data for the subsequent era; if the previous parameter is specified it outputs the data for the previous one. If the old parameter is specified, the module outputs the data for the "old" era. This is the same as the current era unless the year is set to the first year of the specified era. If this is the case, then old outputs the data for the previous era. However, if the module could not find a valid previous era then the data for the current era is returned.

Code Output
{{#invoke:Japanese calendar|baseyear|era=Shōwa period}} Script error: The function "baseyear" does not exist.
{{#invoke:Japanese calendar|baseyear|era=Shōwa period|next=yes}} Script error: The function "baseyear" does not exist.
{{#invoke:Japanese calendar|baseyear|era=Shōwa period|previous=yes}} Script error: The function "baseyear" does not exist.
{{#invoke:Japanese calendar|baseyear|era=Shōwa period|old=yes}} Script error: The function "baseyear" does not exist.
{{#invoke:Japanese calendar|link|year=1880}} Script error: The function "link" does not exist.
{{#invoke:Japanese calendar|link|year=1880|next=yes}} Script error: The function "link" does not exist.
{{#invoke:Japanese calendar|link|year=1880|previous=yes}} Script error: The function "link" does not exist.
{{#invoke:Japanese calendar|link|year=1880|old=yes}} Script error: The function "link" does not exist.
{{#invoke:Japanese calendar|link_year|year=1926}} Script error: The function "link_year" does not exist.
{{#invoke:Japanese calendar|link_year|year=1926|old=yes}} Script error: The function "link_year" does not exist.
{{#invoke:Japanese calendar|link_year|year=1927}} Script error: The function "link_year" does not exist.
{{#invoke:Japanese calendar|link_year|year=1927|old=yes}} Script error: The function "link_year" does not exist.

From another Lua module

First of all, the era class must be loaded, like this:

local era = require( 'Module:Japanese calendar' ).era

Once the class is loaded, you can make a new era object using era:new():

local myEra = era:new{ year = year, era = article name or kanji }

Either year or era must be specified. It is also possible to use an index field, corresponding to the index of Module:Japanese calendar/data, but this is for internal use only and will change as new eras are added.

Properties

Era objects have a number of properties. Their values might be nil if the module did not have enough information to process them, or the values could be false if they correspond to an invalid era. You can specify properties with the dot syntax:

local article = myEra.article

The properties are as follows:

  • gregorianYear: the year in the Gregorian calendar. Same as the input year.
  • startYear: the first year of the specified era.
  • endYear: the last year of the specified era.
  • eraYear: the year of the specified era, without the era name.
  • eraYearKanji: a string representing the era year in kanji. The first year of an era is changed to the kanji 元, and the others are changed to full-width numbers. Note: even though the output may often look like a number, it will always be a string value.
  • article: the Wikipedia article for the era, unlinked.
  • label: the name of the era. Same as article unless the article title is disambiguated.
  • kanji: the name of the era in kanji.
Methods

Era objects have three methods. Methods can be specified with the colon syntax:

local nextEra = myEra:getNextEra()

The methods are as follows:

  • era:getNextEra() - gets the era object for the next era. Returns nil if it doesn't exist.
  • era:getPreviousEra() - gets the era object for the previous era. Returns nil if it doesn't exist.
  • era:getOldEra() - gets the era object for the "old" era. This is the same as the current era object unless eraYear equals 1. If eraYear equals 1 then this returns the era object for the previous era. If the module could not find a valid previous era object then the current era object is returned.

local eras = mw.loadData( 'Module:Japanese calendar/data' )

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

local function yearToEraIndex( year )
    local currentYear = tonumber( mw.language.getContentLanguage():formatDate( 'Y' ) )
    year = tonumber( year )
    if type( year ) ~= 'number' or year > currentYear then return end
    for i, t in ipairs( eras ) do
        if year >= t.year then
            return i
        end
    end
end

local function textToEraIndex( s )
    for i, t in ipairs( eras ) do
        if s == t.article or s == t.kanji then
            return i
        end
    end
end

--------------------------------------------------------------------
-- Era class definition
--------------------------------------------------------------------

local era = {}
era.__index = era

function era:new( init )
    init = type( init ) == 'table' and init or {}
    local obj = {}
    
    -- Grab the data from the init table.
    obj.gregorianYear = tonumber( init.year )
    obj.article = type( init.article ) == 'string' and init.article or nil
    obj.kanji = type( init.kanji ) == 'string' and init.kanji or nil
    
    -- Calculate the era data from the input. Some input values may be overwritten if they are inconsistent with the data in the /data subpage.
    -- If the article name and the kanji differ, the article name takes priority.
    if obj.gregorianYear then
        -- We have the Gregorian year, so we can calculate all the data.
        -- Check if the article or the kanji have been specified, in case the era is different from the year era.
        local eraIndex
        if obj.article or obj.kanji then
            eraIndex = textToEraIndex( obj.article ) or textToEraIndex( obj.kanji )
        else
            eraIndex = yearToEraIndex( obj.gregorianYear )
        end
        
        if eraIndex then
            local eraData = eras[ eraIndex ]
            obj.startYear = eraData.year
            -- Allow matching years to different eras, but only for the first year of the next era. For example, Taisho 14 is also Showa 1, but there is no such thing as Taisho 15.
            if eraIndex > 1 then
                local nextEraData = eras[ eraIndex - 1 ]
                local nextStartYear = nextEraData.year
                if obj.gregorianYear <= nextStartYear and obj.gregorianYear >= obj.startYear and math.floor( obj.gregorianYear ) ~= 687 then -- 686 is a special case as the Shuchō era lasted for less than one year. Disallowing 687 is a quick fix for this.
                    obj.eraYear = obj.gregorianYear - obj.startYear + 1
                    obj.eraYearKanji = tostring( obj.eraYear ) -- Although most of these will be numbers, one is a kanji character, so convert them all to strings.
                    if obj.eraYearKanji == '1' then
                        obj.eraYearKanji = '元'
                    end
                end
            end
            
            obj.article = eraData.article
            obj.kanji = eraData.kanji
            obj.label = eraData.label
        end
    
    elseif obj.article or obj.kanji then
        -- No year was specified, so we will take what data we can from the article name or from the kanji.
        local eraIndex = textToEraIndex( obj.article ) or textToEraIndex( obj.kanji )
        if eraIndex then
            local eraData = eras[ eraIndex ]
            obj.startYear = eraData.year
            obj.kanji = eraData.kanji
            obj.label = eraData.label
        end
    end
    -- Create a link to the era article if possible.
    if obj.article then
        if obj.label then
            obj.link = mw.ustring.format( '[[%s|%s]]', obj.article, obj.label )
        else
            obj.link = mw.ustring.format( '[[%s]]', obj.article )
        end
    end
    
    return setmetatable( obj, {
        __index = self
    })
end

return era