Jump to content
Wikipedia The Free Encyclopedia

Module:Age

From Wikipedia, the free encyclopedia
Module documentation[view] [edit] [history] [purge]
This module is rated as ready for general use. It has reached a mature state, is considered relatively stable and bug-free, and may be used wherever appropriate. It can be mentioned on help pages and other Wikipedia resources as an option for new users. To minimise server load and avoid disruptive output, improvements should be developed through sandbox testing rather than repeated trial-and-error editing.
Page template-protected This module is currently protected from editing.
See the protection policy and protection log for more details. Please discuss any changes on the talk page; you may submit an edit request to ask an administrator to make an edit if it is uncontroversial or supported by consensus. You may also request that this page be unprotected.
Warning This Lua module is used on approximately 1,370,000 pages, or roughly 2% of all pages .
To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them.
This module depends on the following other modules:

Templates supported

Module:Age implements the following templates:

Template Required wikitext
{{extract }} {{#invoke:age|extract}}
{{gregorian serial date }} {{#invoke:age|gsd}}
{{time interval }} {{#invoke:age|time_interval}}
{{age in days }} {{#invoke:age|age_generic|template=age_days}}
{{age in days nts }} {{#invoke:age|age_generic|template=age_days_nts}}
{{duration in days }} {{#invoke:age|age_generic|template=duration_days}}
{{duration in days nts }} {{#invoke:age|age_generic|template=duration_days_nts}}
{{age }} {{#invoke:age|age_generic|template=age_full_years}}
{{age nts }} {{#invoke:age|age_generic|template=age_full_years_nts}}
{{age in years }} {{#invoke:age|age_generic|template=age_in_years}}
{{age in years nts }} {{#invoke:age|age_generic|template=age_in_years_nts}}
{{age for infant }} {{#invoke:age|age_generic|template=age_infant}}
{{age in months }} {{#invoke:age|age_generic|template=age_m}}
{{age in weeks }} {{#invoke:age|age_generic|template=age_w}}
{{age in weeks and days }} {{#invoke:age|age_generic|template=age_wd}}
{{age in years and days }} {{#invoke:age|age_generic|template=age_yd}}
{{age in years and days nts }} {{#invoke:age|age_generic|template=age_yd_nts}}
{{age in years and months }} {{#invoke:age|age_generic|template=age_ym}}
{{age in years, months and days }} {{#invoke:age|age_generic|template=age_ymd}}
{{age in years, months, weeks and days }} {{#invoke:age|age_generic|template=age_ymwd}}
{{birth date and age }} {{#invoke:age|birth_date_and_age}}
{{death date and age }} {{#invoke:age|death_date_and_age}}

Redirects

Template Redirects to
{{ayd}} Template:Ayd {{age in years and days nts }}
{{hla}} Template:Hla {{age in years, months and days }}
{{age in months, weeks and days}} Template:Age in months, weeks and days {{age in years, months, weeks and days }}
{{bda}} Template:Bda {{birth date and age }}
{{dda}} Template:Dda {{death date and age }}
{{gsd}} Template:Gsd {{gregorian serial date }}

The age templates expect the older date to be first. The implementations of age_in_years and age_in_years_nts display an error message if that is not the case. If similar checking is wanted for other templates, negative=error can be added to the invoke. For example, {{age }} might use:

  • {{#invoke:age|age_generic|template=age_full_years|negative=error}}

If negative=error does not apply, a negative difference is indicated with a minus sign (−).

Date formats

Dates can use numbered or named parameters to specify year/month/day. Alternatively, a full date can be entered in a variety of formats. For example:

  • {{age in years and months|year1=2001|month1=1|day1=10|year2=2012|month2=2|day2=20}} → 11 years, 1 month
  • {{age in years and months|year=2001|month=1|day=10|year2=2012|month2=2|day2=20}} → 11 years, 1 month
  • {{age in years and months|2001|1|10|2012|2|20}} → 11 years, 1 month
  • {{age in years and months|2001年1月10日|2012年2月20日}} → 11 years, 1 month
  • {{age in years and months|10 Jan 2001|20 Feb 2012}} → 11 years, 1 month
  • {{age in years and months|January 10, 2001|Feb 20, 2012}} → 11 years, 1 month

If the first or second date is omitted, the current date is used. For example:

  • {{age in years and months|year2=2012|month2=2|day2=20}} → −13 years, 8 months
  • {{age in years and months||||2012|2|20}} → −13 years, 8 months
  • {{age in years and months||2012年2月20日}} → −13 years, 8 months
  • {{age in years and months||20 Feb 2012}} → −13 years, 8 months
  • {{age in years and months||Feb 20, 2012}} → −13 years, 8 months
  • {{age in years and months|year1=2001|month1=1|day1=10}} → 24 years, 10 months
  • {{age in years and months|year=2001|month=1|day=10}} → 24 years, 10 months
  • {{age in years and months|2001|1|10}} → 24 years, 10 months
  • {{age in years and months|2001年1月10日}} → 24 years, 10 months
  • {{age in years and months|10 Jan 2001}} → 24 years, 10 months
  • {{age in years and months|January 10, 2001}} → 24 years, 10 months

Parameters

The following options are available:

Parameter Description
duration=on The finishing date is included in the result; that adds one day to the age.
fix=on Adjust invalid time units. See Template:Extract#Fix.
format=commas A value of 1,000 or more is displayed with commas.
format=raw Numbers are displayed without commas and negative numbers are displayed with a hyphen for {{#expr}}. In addition, {{age }} outputs a plain number and will not include a span to indicate if the result relies on the current date.
format=cardinal Display the resulting number using words such as "five" instead of 5. See below.
format=ordinal Display the resulting number using words such as "fifth" instead of 5. See below.
prefix=text Insert the given text before the result but after any sort key. For example, {{age|23 July 1910|14 July 1976|prefix=about|sortable=on}} outputs a hidden sort key followed by "about 65".
range=dash Accept a year only, or a year and month only, and show a range of ages with an en dash (–).
range=yes Accept a year or year/month, and show the range with "or".
range=no Accept a year only, or year/month, but show only a single age as if full dates had been entered.
round=on The age is rounded to the nearest least-significant time unit.
sc=on A serial comma is used (only useful when three or more values are displayed).
sc=yes Same as sc=on.
show=hide The age is not displayed; may be useful with sortable=on.
sortable=on Insert a hidden sort key before the result (for use in sortable tables).
sortable=table Insert a sort key using table syntax data-sort-value="value"|.
sortable=debug Same as sortable=on but the sort key is displayed for testing.
sortable=off No sort key (can override the default for a template like {{age nts }}).

Examples using the range parameter follow.

  • {{age in years and months|year=2001|month=1|year2=2012|month2=2|range=yes}} → 11 years, 0 or 1 month
  • {{age in years and months|2001|1||2012|2|range=yes}} → 11 years, 0 or 1 month
  • {{age in years and months|Jan 2001|Feb 2012|range=yes}} → 11 years, 0 or 1 month
  • {{age in years and months|Jan 2001|Feb 2012|range=dash}} → 11 years, 0–1 month
  • {{age in years and months|Jan 2001|Feb 2012|range=no}} → 11 years, 1 month (assume 1 Jan 2001 to 1 Feb 2012)
  • {{age in years and months|12 Jan 2001|Feb 2012|range=no}} → 11 years, 1 month (assume 12 Jan 2001 to 12 Feb 2012)
  • {{age in years and months|2001|2012|range=no}} → 11 years (assume 1 Jan 2001 to 1 Jan 2012)
  • {{age in years and months|2001|23 Feb 2012|range=no}} → 11 years (assume 23 Feb 2001 to 23 Feb 2012)

The sort key is based on the age in days, and fractions of a day if a time is specified.

  • {{age in years and months|10 Jan 2001|20 Feb 2012|sortable=debug}}7003405800000000000♠11 years, 1 month
  • {{age in years and months|10 Jan 2001|6:00 am 20 Feb 2012|sortable=debug}}7003405825000000000♠11 years, 1 month
  • {{age in years and months|10 Jan 2001|6:00 am 20 Feb 2012|sortable=debug|show=hide}}7003405825000000000♠

An extra day is added for a duration.

  • {{age in years and months|20 Jan 2001|19 Feb 2012}} → 11 years (one day short of 11 years, 1 month)
  • {{age in years and months|20 Jan 2001|19 Feb 2012|duration=on}} → 11 years, 1 month

The least-significant time unit can be rounded.

  • {{age in years and months|20 Jan 2001|10 Feb 2012}} → 11 years
  • {{age in years and months|20 Jan 2001|10 Feb 2012|round=on}} → 11 years, 1 month (round to nearest month)

Large numbers can be formatted with commas.

  • {{age in years and months|120|2012|format=commas|range=yes}} → 1,891 or 1,892 years
  • {{age in years and months|120|2012|format=commas|range=dash}} → 1,891–1,892 years

Spelling numbers

The templates that use age_generic can display numbers in words rather than using numerals. The result can be a cardinal number (such as "five") or an ordinal number (such as "fifth"). The first letter can be in uppercase, and US spelling of numbers can be used. Examples:

  • {{age|1898|01|01|2018|02|01|format=cardinal}} → one hundred and twenty
  • {{age|1898|01|01|2018|02|01|format=cardinal_us}} → one hundred twenty
  • {{age|1898|01|01|2018|02|01|format=Cardinal}} → One hundred and twenty
  • {{age|1898|01|01|2018|02|01|format=Cardinal_us}} → One hundred twenty
  • {{age|1898|01|01|2018|02|01|format=Ordinal}} → One hundred and twentieth
  • {{age|1898|01|01|2018|02|01|format=Ordinal_us}} → One hundred twentieth
  • {{age|1898|01|01|2018|02|01|format=ordinal}} → one hundred and twentieth
  • {{age|1898|01|01|2018|02|01|format=ordinal_us}} → one hundred twentieth
  • {{age|1980|1990|range=yes|format=Cardinal}} → Nine or ten
  • {{age in years, months and days|April 1980|1995|format=Cardinal|range=yes}} → Fourteen or fifteen years

Tracking category

Localization

Inputs and outputs can be localized to suit the language used. Examples are at bnwiki and bswiki.

See also

  • {{time interval }} • This template supports all age/duration calculations and provides more options such as abbreviating or omitting units.
The above documentation is transcluded from Module:Age/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (edit | run) pages.
Subpages of this module.

 -- Implement various "age of" and other date-related templates.

 localmtext={
 -- Message and other text that should be localized.
 -- Also need to localize text in table names in function dateDifference.
 ['mt-bad-param2']='Parameter 1ドル=2ドル is invalid',
 ['mt-bad-show']='Parameter show=1ドル is not supported here',
 ['mt-cannot-add']='Cannot add "1ドル"',
 ['mt-conflicting-show']='Parameter show=1ドル conflicts with round=2ドル',
 ['mt-date-wrong-order']='The second date must be later in time than the first date',
 ['mt-dd-future']='Death date (first date) must not be in the future',
 ['mt-dd-wrong-order']='Death date (first date) must be later in time than the birth date (second date)',
 ['mt-invalid-bd-age']='Invalid birth date for calculating age',
 ['mt-invalid-dates-age']='Invalid dates for calculating age',
 ['mt-invalid-end']='Invalid end date in second parameter',
 ['mt-invalid-start']='Invalid start date in first parameter',
 ['mt-need-jdn']='Need valid Julian date number',
 ['mt-need-valid-bd']='Need valid birth date: year, month, day',
 ['mt-need-valid-bd2']='Need valid birth date (second date): year, month, day',
 ['mt-need-valid-date']='Need valid date',
 ['mt-need-valid-dd']='Need valid death date (first date): year, month, day',
 ['mt-need-valid-ymd']='Need valid year, month, day',
 ['mt-need-valid-ymd-current']='Need valid year|month|day or "currentdate"',
 ['mt-need-valid-ymd2']='Second date should be year, month, day',
 ['mt-template-bad-name']='The specified template name is not valid',
 ['mt-template-x']='The template invoking this must have "|template=x" where x is the wanted operation',
 ['mt-warn-param1']='Invalid parameter 1ドル',
 ['mt-warn-param2']='Parameter 1ドル=2ドル is invalid',
 ['txt-affirmative']={y=true,yes=true,Y=true,Yes=true,YES=true},-- valid values for df + mf parameters
 ['txt-yes']={y=true,yes=true,on=true},-- valid values for parameters introduced with this module
 ['txt-and']=' and ',
 ['txt-or']=' or ',
 ['txt-category']='Category:Pages using age template with invalid date',
 ['txt-comma-and']=', and ',
 ['txt-error']='Error: ',
 ['txt-format-default']='mf',-- 'df' (day first = dmy) or 'mf' (month first = mdy)
 ['txt-module-convertnumeric']='Module:ConvertNumeric',
 ['txt-module-date']='Module:Date',
 ['txt-sandbox']='sandbox',
 ['txt-bda']='<span style="display:none"> (<span class="bday">1ドル</span>) </span>2ドル<span class="noprint ForceAgeToShow"> (age&nbsp;3ドル)</span>',
 ['txt-dda']='2ドル<span style="display:none">(1ドル)</span> (aged&nbsp;3ドル)',
 ['txt-bda-disp']='disp_raw',-- disp_raw → age is a number only; disp_age → age is a number and unit (normally years but months or days if very young)
 ['txt-dda-disp']='disp_raw',
 ['txt-dmy']='%-d %B %-Y',
 ['txt-mdy']='%B %-d, %-Y',
 }

 localisWarning={
 ['mt-warn-param1']=true,
 ['mt-warn-param2']=true,
 }

 -- yes[parameter] is true if parameter should be interpreted as "yes".
 -- Do not want to accept mixed upper/lowercase unless done by previously used templates.
 -- Need to accept "on" because "round=on" is wanted.
 localyes=mtext['txt-yes']

 -- Max valid age.
 localMAX_AGE=130

 localtranslate,from_en,to_en,isZero
 iftranslatethen
 -- Functions to translate from en to local language and reverse go here.
 -- See example at [[:bn:Module:বয়স]].
 else
 from_en=function(text)
 returntext
 end
 isZero=function(text)
 returntonumber(text)==0
 end
 end

 local_Date,_currentDate
 localfunctiongetExports(frame)
 -- Return objects exported from the date module or its sandbox.
 ifnot_Datethen
 localsandbox=frame:getTitle():find(mtext['txt-sandbox'],1,true)and('/'..mtext['txt-sandbox'])or''
 localdatemod=require(mtext['txt-module-date']..sandbox)
 localrealDate=datemod._Date
 _currentDate=datemod._current
 ifto_enthen
 _Date=function(...)
 localargs={}
 fori,vinipairs({...})do
 args[i]=to_en(v)
 end
 returnrealDate(unpack(args))
 end
 else
 _Date=realDate
 end
 end
 return_Date,_currentDate
 end

 localCollection-- a table to hold items
 Collection={
 add=function(self,item)
 ifitem~=nilthen
 self.n=self.n+1
 self[self.n]=item
 end
 end,
 join=function(self,sep)
 returntable.concat(self,sep)
 end,
 remove=function(self,pos)
 ifself.n>0and(pos==nilor(0<posandpos<=self.n))then
 self.n=self.n-1
 returntable.remove(self,pos)
 end
 end,
 sort=function(self,comp)
 table.sort(self,comp)
 end,
 new=function()
 returnsetmetatable({n=0},Collection)
 end
 }
 Collection.__index=Collection

 localfunctionstripToNil(text)
 -- If text is a string, return its trimmed content, or nil if empty.
 -- Otherwise return text (which may, for example, be nil).
 iftype(text)=='string'then
 text=text:match('(%S.-)%s*$')
 end
 returntext
 end

 localfunctionsubstituteParameters(text,...)
 -- Return text after substituting any given parameters for 1,ドル 2,ドル etc.
 returnmw.message.newRawMessage(text,...):plain()
 end

 localfunctionmessage(msg,...)
 -- Return formatted message text for an error or warning.
 localfunctiongetText(msg)
 returnmtext[msg]orerror('Bug: message "'..tostring(msg)..'" not defined')
 end
 localcategories={
 error=mtext['txt-category'],
 warning=mtext['txt-category'],
 }
 locala,b,k,category
 localtext=substituteParameters(getText(msg),...)
 ifisWarning[msg]then
 a='<sup>[<i>'
 b='</i>]</sup>'
 k='warning'
 else
 a='<strong class="error">'..getText('txt-error')
 b='</strong>'
 k='error'
 end
 ifmw.title.getCurrentTitle():inNamespaces(0)then
 -- Category only in namespaces: 0=article.
 category='[['..categories[k]..']]'
 end
 return
 a..
 mw.text.nowiki(text)..
 b..
 (categoryor'')
 end

 localfunctiondateFormat(args)
 -- Return
 -- nil, f	if parameter is valid
 -- m, f otherwise
 -- where
 -- m = string for warning message with category
 -- f = string for wanted date format
 localproblem
 localwanted=mtext['txt-format-default']
 localother=wanted=='df'and'mf'or'df'
 localparm=args[other]or''
 ifmtext['txt-affirmative'][parm]then
 wanted=other
 elseifparm~=''then
 problem=message('mt-warn-param2',other,parm)
 end
 returnproblem,wanted=='df'andmtext['txt-dmy']ormtext['txt-mdy']
 end

 localfunctionformatNumber(number)
 -- Return the given number formatted with commas as group separators,
 -- given that the number is an integer.
 localnumstr=tostring(number)
 locallength=#numstr
 localplaces=Collection.new()
 localpos=0
 repeat
 places:add(pos)
 pos=pos+3
 untilpos>=length
 places:add(length)
 localgroups=Collection.new()
 fori=places.n,2,-1do
 localp1=length-places[i]+1
 localp2=length-places[i-1]
 groups:add(numstr:sub(p1,p2))
 end
 returngroups:join(',')
 end

 localfunctionspellNumber(number,options,i)
 -- Return result of spelling number, or
 -- return number (as a string) if cannot spell it.
 -- i == 1 for the first number which can optionally start with an uppercase letter.
 number=tostring(number)
 returnrequire(mtext['txt-module-convertnumeric']).spell_number(
 number,
 nil,-- fraction numerator
 nil,-- fraction denominator
 i==1andoptions.upper,-- true: 'One' instead of 'one'
 notoptions.us,-- true: use 'and' between tens/ones etc
 options.adj,-- true: hyphenated
 options.ordinal-- true: 'first' instead of 'one'
 )ornumber
 end

 localfunctionmakeExtra(args,flagCurrent)
 -- Return extra text that will be inserted before the visible result
 -- but after any sort key.
 localextra=args.prefixor''
 ifmw.ustring.len(extra)>1then
 -- Parameter "~" gives "~3" whereas "over" gives "over 3".
 ifextra:sub(-6,-1)~='&nbsp;'then
 extra=extra..' '
 end
 end
 ifflagCurrentthen
 extra='<span class="currentage"></span>'..extra
 end
 returnextra
 end

 localfunctionmakeSort(value,sortable)
 -- Return a sort key if requested.
 -- Assume value is a valid number which has not overflowed.
 ifsortable=='sortable_table'orsortable=='sortable_on'orsortable=='sortable_debug'then
 localsortKey
 ifvalue==0then
 sortKey='5000000000000000000'
 else
 localmag=math.floor(math.log10(math.abs(value))+1e-14)
 ifvalue>0then
 sortKey=7000+mag
 else
 sortKey=2999-mag
 value=value+10^(mag+1)
 end
 sortKey=string.format('%d',sortKey)..string.format('%015.0f',math.floor(value*10^(14-mag)))
 end
 localresult
 ifsortable=='sortable_table'then
 result='data-sort-value="_SORTKEY_"|'
 elseifsortable=='sortable_debug'then
 result='<span data-sort-value="_SORTKEY_♠"><span style="border:1px solid">_SORTKEY_♠</span></span>'
 else
 result='<span data-sort-value="_SORTKEY_♠"></span>'
 end
 return(result:gsub('_SORTKEY_',sortKey))
 end
 end

 localtranslateParameters={
 abbr={
 off='abbr_off',
 on='abbr_on',
 },
 disp={
 age='disp_age',
 raw='disp_raw',
 },
 format={
 raw='format_raw',
 commas='format_commas',
 },
 round={
 on='on',
 yes='on',
 months='ym',
 weeks='ymw',
 days='ymd',
 hours='ymdh',
 },
 sep={
 comma='sep_comma',
 [',']='sep_comma',
 serialcomma='sep_serialcomma',
 space='sep_space',
 },
 show={
 hide={id='hide'},
 y={'y',id='y'},
 ym={'y','m',id='ym'},
 ymd={'y','m','d',id='ymd'},
 ymw={'y','m','w',id='ymw'},
 ymwd={'y','m','w','d',id='ymwd'},
 yd={'y','d',id='yd',keepZero=true},
 m={'m',id='m'},
 md={'m','d',id='md'},
 w={'w',id='w'},
 wd={'w','d',id='wd'},
 h={'H',id='h'},
 hm={'H','M',id='hm'},
 hms={'H','M','S',id='hms'},
 M={'M',id='M'},
 s={'S',id='s'},
 d={'d',id='d'},
 dh={'d','H',id='dh'},
 dhm={'d','H','M',id='dhm'},
 dhms={'d','H','M','S',id='dhms'},
 ymdh={'y','m','d','H',id='ymdh'},
 ymdhm={'y','m','d','H','M',id='ymdhm'},
 ymwdh={'y','m','w','d','H',id='ymwdh'},
 ymwdhm={'y','m','w','d','H','M',id='ymwdhm'},
 },
 sortable={
 off=false,
 on='sortable_on',
 table='sortable_table',
 debug='sortable_debug',
 },
 }

 localspellOptions={
 cardinal={},
 Cardinal={upper=true},
 cardinal_us={us=true},
 Cardinal_us={us=true,upper=true},
 ordinal={ordinal=true},
 Ordinal={ordinal=true,upper=true},
 ordinal_us={ordinal=true,us=true},
 Ordinal_us={ordinal=true,us=true,upper=true},
 }

 localfunctiondateExtract(frame)
 -- Return part of a date after performing an optional operation.
 localDate=getExports(frame)
 localargs=frame:getParent().args
 localparms={}
 fori,vinipairs(args)do
 parms[i]=v
 end
 ifyes[args.fix]then
 table.insert(parms,'fix')
 end
 ifyes[args.partial]then
 table.insert(parms,'partial')
 end
 localshow=stripToNil(args.show)or'dmy'
 localdate=Date(unpack(parms))
 ifnotdatethen
 ifshow=='format'then
 return'error'
 end
 returnmessage('mt-need-valid-date')
 end
 localadd=stripToNil(args.add)
 ifaddthen
 foriteminadd:gmatch('%S+')do
 date=date+item
 ifnotdatethen
 returnmessage('mt-cannot-add',item)
 end
 end
 end
 localsortKey,result
 localsortable=translateParameters.sortable[args.sortable]
 ifsortablethen
 localvalue=(date.partialanddate.partial.firstordate).jdz
 sortKey=makeSort(value,sortable)
 end
 ifshow~='hide'then
 result=date[show]
 ifresult==nilthen
 result=from_en(date:text(show))
 elseiftype(result)=='boolean'then
 result=resultand'1'or'0'
 else
 result=from_en(tostring(result))
 end
 end
 return(sortKeyor'')..makeExtra(args)..(resultor'')
 end

 localfunctionrangeJoin(range)
 -- Return text to be used between a range of ages.
 returnrange=='dash'and'–'ormtext['txt-or']
 end

 localfunctionmakeText(values,components,names,options,noUpper)
 -- Return wikitext representing an age or duration.
 localtext=Collection.new()
 localcount=#values
 localsep=names.sepor''
 fori,vinipairs(values)do
 -- v is a number (say 4 for 4 years), or a table ({4,5} for 4 or 5 years).
 localislist=type(v)=='table'
 if(islistorv>0)or(text.n==0andi==count)or(text.n>0andcomponents.keepZero)then
 localfmt,vstr
 ifoptions.spellthen
 fmt=function(number)
 returnspellNumber(number,options.spell,noUpperori)
 end
 elseifi==1andoptions.format=='format_commas'then
 -- Numbers after the first should be small and not need formatting.
 fmt=formatNumber
 else
 fmt=tostring
 end
 ifislistthen
 vstr=fmt(v[1])..rangeJoin(options.range)
 noUpper=true
 vstr=vstr..fmt(v[2])
 else
 vstr=fmt(v)
 end
 localname=names[components[i]]
 ifnamethen
 iftype(name)=='table'then
 name=mw.getContentLanguage():plural(islistandv[2]orv,name)
 end
 text:add(vstr..sep..name)
 else
 text:add(vstr)
 end
 end
 end
 localfirst,last
 ifoptions.join=='sep_space'then
 first=' '
 last=' '
 elseifoptions.join=='sep_comma'then
 first=', '
 last=', '
 elseifoptions.join=='sep_serialcomma'andtext.n>2then
 first=', '
 last=mtext['txt-comma-and']
 else
 first=', '
 last=mtext['txt-and']
 end
 fori,vinipairs(text)do
 ifi<text.nthen
 text[i]=v..(i+1<text.nandfirstorlast)
 end
 end
 localsign=''
 ifoptions.isnegativethen
 -- Do not display negative zero.
 iftext.n>1or(text.n==1andtext[1]:sub(1,1)~='0')then
 ifoptions.format=='format_raw'then
 sign='-'-- plain hyphen so result can be used in a calculation
 else
 sign='−'-- Unicode U+2212 MINUS SIGN
 end
 end
 end
 return
 (options.sortKeyor'')..
 (options.extraor'')..
 sign..
 text:join()..
 (options.suffixor'')
 end

 localfunctiondateDifference(parms)
 -- Return a formatted date difference using the given parameters
 -- which have been validated.
 localnames={
 -- Each name is:
 -- * a string if no plural form of the name is used; or
 -- * a table of strings, one of which is selected using the rules at
 -- https://translatewiki.net/wiki/Plural/Mediawiki_plural_rules
 abbr_off={
 sep='&nbsp;',
 y={'year','years'},
 m={'month','months'},
 w={'week','weeks'},
 d={'day','days'},
 H={'hour','hours'},
 M={'minute','minutes'},
 S={'second','seconds'},
 },
 abbr_on={
 y='y',
 m='m',
 w='w',
 d='d',
 H='h',
 M='m',
 S='s',
 },
 abbr_infant={-- for {{age for infant}}
 sep='&nbsp;',
 y={'yr','yrs'},
 m={'mo','mos'},
 w={'wk','wks'},
 d={'day','days'},
 H={'hr','hrs'},
 M={'min','mins'},
 S={'sec','secs'},
 },
 abbr_raw={},
 }
 localdiff=parms.diff-- must be a valid date difference
 localshow=parms.show-- may be nil; default is set below
 localabbr=parms.abbror'abbr_off'
 localdefaultJoin
 ifabbr~='abbr_off'then
 defaultJoin='sep_space'
 end
 ifnotshowthen
 show='ymd'
 ifparms.disp=='disp_age'then
 ifdiff.years<3then
 defaultJoin='sep_space'
 ifdiff.years>=1then
 show='ym'
 else
 show='md'
 end
 else
 show='y'
 end
 end
 end
 iftype(show)~='table'then
 show=translateParameters.show[show]
 end
 ifparms.disp=='disp_raw'then
 defaultJoin='sep_space'
 abbr='abbr_raw'
 elseifparms.wantScthen
 defaultJoin='sep_serialcomma'
 end
 localdiffOptions={
 round=parms.round,
 duration=parms.wantDuration,
 range=parms.rangeandtrueornil,
 }
 localsortKey
 ifparms.sortablethen
 localvalue=diff.age_days+(parms.wantDurationand1or0)-- days and fraction of a day
 ifdiff.isnegativethen
 value=-value
 end
 sortKey=makeSort(value,parms.sortable)
 end
 localtextOptions={
 extra=parms.extra,
 format=parms.format,
 join=parms.sepordefaultJoin,
 isnegative=diff.isnegative,
 range=parms.range,
 sortKey=sortKey,
 spell=parms.spell,
 suffix=parms.suffix,-- not currently used
 }
 ifshow.id=='hide'then
 returnsortKeyor''
 end
 localvalues={diff:age(show.id,diffOptions)}
 ifvalues[1]then
 returnmakeText(values,show,names[abbr],textOptions)
 end
 ifdiff.partialthen
 -- Handle a more complex range such as
 -- {{age_yd|20 Dec 2001|2003|range=yes}} → 1 year, 12 days or 2 years, 11 days
 localopt={
 format=textOptions.format,
 join=textOptions.join,
 isnegative=textOptions.isnegative,
 spell=textOptions.spell,
 }
 return
 (textOptions.sortKeyor'')..
 makeText({diff.partial.mindiff:age(show.id,diffOptions)},show,names[abbr],opt)..
 rangeJoin(textOptions.range)..
 makeText({diff.partial.maxdiff:age(show.id,diffOptions)},show,names[abbr],opt,true)..
 (textOptions.suffixor'')
 end
 returnmessage('mt-bad-show',show.id)
 end

 localfunctiongetDates(frame,getopt)
 -- Parse template parameters and return one of:
 -- * date (a date table, if single)
 -- * date1, date2 (two date tables, if not single)
 -- * text (a string error message)
 -- A missing date is optionally replaced with the current date.
 -- If wantMixture is true, a missing date component is replaced
 -- from the current date, so can get a bizarre mixture of
 -- specified/current y/m/d as has been done by some "age" templates.
 -- Some results may be placed in table getopt.
 localDate,currentDate=getExports(frame)
 getopt=getoptor{}
 localfunctionflagCurrent(text)
 -- This allows the calling template to detect if the current date has been used,
 -- that is, whether both dates have been entered in a template expecting two.
 -- For example, an infobox may want the age when an event occurred, not the current age.
 -- Don't bother detecting if wantMixture is used because not needed and it is a poor option.
 ifnottextthen
 ifgetopt.noMissingthen
 returnnil-- this gives a nil date which gives an error
 end
 text='currentdate'
 ifgetopt.flag=='usesCurrent'then
 getopt.usesCurrent=true
 end
 end
 returntext
 end
 localargs=frame:getParent().args
 localfields={}
 localisNamed=args.yearorargs.year1orargs.year2or
 args.monthorargs.month1orargs.month2or
 args.dayorargs.day1orargs.day2
 ifisNamedthen
 fields[1]=args.year1orargs.year
 fields[2]=args.month1orargs.month
 fields[3]=args.day1orargs.day
 fields[4]=args.year2
 fields[5]=args.month2
 fields[6]=args.day2
 else
 fori=1,6do
 fields[i]=args[i]
 end
 end
 localimax=0
 fori=1,6do
 fields[i]=stripToNil(fields[i])
 iffields[i]then
 imax=i
 end
 ifgetopt.omitZeroandi%3~=1then-- omit zero months and days as unknown values but keep year 0 which is 1 BCE
 ifisZero(fields[i])then
 fields[i]=nil
 getopt.partial=true
 end
 end
 end
 localfix=getopt.fixand'fix'or''
 localpartialText=getopt.partialand'partial'or''
 localdates={}
 ifisNamedorimax>=3then
 localnrDates=getopt.singleand1or2
 ifgetopt.wantMixturethen
 -- Cannot be partial since empty fields are set from current.
 localcomponents={'year','month','day'}
 fori=1,nrDates*3do
 fields[i]=fields[i]orcurrentDate[components[i>3andi-3ori]]
 end
 fori=1,nrDatesdo
 localindex=i==1and1or4
 localy,m,d=fields[index],fields[index+1],fields[index+2]
 if(m==2orm=='2')and(d==29ord=='29')then
 -- Workaround error with following which attempt to use invalid date 2001-02-29.
 -- {{age_ymwd|year1=2001|year2=2004|month2=2|day2=29}}
 -- {{age_ymwd|year1=2001|month1=2|year2=2004|month2=1|day2=29}}
 -- TODO Get rid of wantMixture because even this ugly code does not handle
 -- 'Feb' or 'February' or 'feb' or 'february'.
 ifnot((y%4==0andy%100~=0)ory%400==0)then
 d=28
 end
 end
 dates[i]=Date(y,m,d)
 end
 else
 -- If partial dates are allowed, accept
 -- year only, or
 -- year and month only
 -- Do not accept year and day without a month because that makes no sense
 -- (and because, for example, Date('partial', 2001, nil, 12) sets day = nil, not 12).
 fori=1,nrDatesdo
 localindex=i==1and1or4
 localy,m,d=fields[index],fields[index+1],fields[index+2]
 if(getopt.partialandyand(mornotd))or(yandmandd)then
 dates[i]=Date(fix,partialText,y,m,d)
 elseifnotyandnotmandnotdthen
 dates[i]=Date(flagCurrent())
 end
 end
 end
 else
 getopt.textdates=true-- have parsed each date from a single text field
 dates[1]=Date(fix,partialText,flagCurrent(fields[1]))
 ifnotgetopt.singlethen
 dates[2]=Date(fix,partialText,flagCurrent(fields[2]))
 end
 end
 ifnotdates[1]then
 returnmessage(getopt.missing1or'mt-need-valid-ymd')
 end
 ifgetopt.singlethen
 returndates[1]
 end
 ifnotdates[2]then
 returnmessage(getopt.missing2or'mt-need-valid-ymd2')
 end
 returndates[1],dates[2]
 end

 localfunctionageGeneric(frame)
 -- Return the result required by the specified template.
 -- Can use sortable=x where x = on/table/off/debug in any supported template.
 -- Some templates default to sortable=on but can be overridden.
 localname=frame.args.template
 ifnotnamethen
 returnmessage('mt-template-x')
 end
 localargs=frame:getParent().args
 localspecs={
 age_days={-- {{age in days}}
 show='d',
 disp='disp_raw',
 },
 age_days_nts={-- {{age in days nts}}
 show='d',
 disp='disp_raw',
 format='format_commas',
 sortable='on',
 },
 duration_days={-- {{duration in days}}
 show='d',
 disp='disp_raw',
 duration=true,
 },
 duration_days_nts={-- {{duration in days nts}}
 show='d',
 disp='disp_raw',
 format='format_commas',
 sortable='on',
 duration=true,
 },
 age_full_years={-- {{age}}
 show='y',
 abbr='abbr_raw',
 flag='usesCurrent',
 omitZero=true,
 range='dash',
 },
 age_full_years_nts={-- {{age nts}}
 show='y',
 abbr='abbr_raw',
 format='format_commas',
 sortable='on',
 },
 age_in_years={-- {{age in years}}
 show='y',
 abbr='abbr_raw',
 negative='error',
 range='dash',
 },
 age_in_years_nts={-- {{age in years nts}}
 show='y',
 abbr='abbr_raw',
 negative='error',
 range='dash',
 format='format_commas',
 sortable='on',
 },
 age_infant={-- {{age for infant}}
 -- Do not set show because special processing is done later.
 abbr=yes[args.abbr]and'abbr_infant'or'abbr_off',
 disp='disp_age',
 sep='sep_space',
 sortable='on',
 },
 age_m={-- {{age in months}}
 show='m',
 disp='disp_raw',
 },
 age_w={-- {{age in weeks}}
 show='w',
 disp='disp_raw',
 },
 age_wd={-- {{age in weeks and days}}
 show='wd',
 },
 age_yd={-- {{age in years and days}}
 show='yd',
 format='format_commas',
 sep=args.sep~='and'and'sep_comma'ornil,
 },
 age_yd_nts={-- {{age in years and days nts}}
 show='yd',
 format='format_commas',
 sep=args.sep~='and'and'sep_comma'ornil,
 sortable='on',
 },
 age_ym={-- {{age in years and months}}
 show='ym',
 sep='sep_comma',
 },
 age_ymd={-- {{age in years, months and days}}
 show='ymd',
 range=true,
 },
 age_ymwd={-- {{age in years, months, weeks and days}}
 show='ymwd',
 wantMixture=true,
 },
 }
 localspec=specs[name]
 ifnotspecthen
 returnmessage('mt-template-bad-name')
 end
 ifname=='age_days'then
 localsu=stripToNil(args['show unit'])
 ifsuthen
 ifsu=='abbr'orsu=='full'then
 spec.disp=nil
 spec.abbr=su=='abbr'and'abbr_on'ornil
 end
 end
 end
 localpartial,autofill
 localrange=stripToNil(args.range)orspec.range
 ifrangethen
 -- Suppose partial dates are used and age could be 11 or 12 years.
 -- "|range=" (empty value) has no effect (spec is used).
 -- "|range=yes" or spec.range == true sets range = true (gives "11 or 12")
 -- "|range=dash" or spec.range == 'dash' sets range = 'dash' (gives "11–12").
 -- "|range=no" or spec.range == 'no' sets range = nil and fills each date in the diff (gives "12").
 -- ("on" is equivalent to "yes", and "off" is equivalent to "no").
 -- "|range=OTHER" sets range = nil and rejects partial dates.
 range=({dash='dash',off='no',no='no',[true]=true})[range]oryes[range]
 ifrangethen
 partial=true-- accept partial dates with a possible age range for the result
 ifrange=='no'then
 autofill=true-- missing month/day in first or second date are filled from other date or 1
 range=nil
 end
 end
 end
 localgetopt={
 fix=yes[args.fix],
 flag=stripToNil(args.flag)orspec.flag,
 omitZero=spec.omitZero,
 partial=partial,
 wantMixture=spec.wantMixture,
 }
 localdate1,date2=getDates(frame,getopt)
 iftype(date1)=='string'then
 returndate1
 end
 localformat=stripToNil(args.format)
 localspell=spellOptions[format]
 ifformatthen
 format='format_'..format
 elseifname=='age_days'andgetopt.textdatesthen
 format='format_commas'
 end
 localparms={
 diff=date2:subtract(date1,{fill=autofill}),
 wantDuration=spec.durationoryes[args.duration],
 range=range,
 wantSc=yes[args.sc],
 show=args.show=='hide'and'hide'orspec.show,
 abbr=spec.abbr,
 disp=spec.disp,
 extra=makeExtra(args,getopt.usesCurrentandformat~='format_raw'),
 format=formatorspec.format,
 round=yes[args.round],
 sep=spec.sep,
 sortable=translateParameters.sortable[args.sortableorspec.sortable],
 spell=spell,
 }
 if(spec.negativeorframe.args.negative)=='error'andparms.diff.isnegativethen
 returnmessage('mt-date-wrong-order')
 end
 returnfrom_en(dateDifference(parms))
 end

 localfunctionisFake(args)
 -- Some templates have TemplateData with an auto value like "{{Birth date and age|YYYY|MM|DD}}".
 -- Return true if that appears to be the case so the caller can output nothing rather than an error.
 returnargs[1]=='YYYY'
 end

 localfunctionbda(frame)
 -- Implement [[Template:Birth date and age]].
 localargs=frame:getParent().args
 ifisFake(args)then
 return''
 end
 localoptions={
 missing1='mt-need-valid-bd',
 noMissing=true,
 single=true,
 }
 localdate=getDates(frame,options)
 iftype(date)=='string'then
 returndate-- error text
 end
 localDate=getExports(frame)
 localdiff=Date('currentdate')-date
 ifdiff.isnegativeordiff.years>MAX_AGEthen
 returnmessage('mt-invalid-bd-age')
 end
 localdisp=mtext['txt-bda-disp']
 localshow='y'
 ifdiff.years<2then
 disp='disp_age'
 ifdiff.years==0anddiff.months==0then
 show='d'
 else
 show='m'
 end
 end
 localproblem,format=dateFormat(args)
 localresult=substituteParameters(
 mtext['txt-bda'],
 date:text('%-Y-%m-%d'),
 from_en(date:text(format)),
 from_en(dateDifference({
 diff=diff,
 show=show,
 abbr='abbr_off',
 disp=disp,
 sep='sep_space',
 }))
 )..(problemor'')
 localwarnings=tonumber(frame.args.warnings)
 ifwarningsandwarnings>0then
 localgood={
 df=true,
 mf=true,
 day=true,
 day1=true,
 month=true,
 month1=true,
 year=true,
 year1=true,
 }
 localinvalid
 localimax=options.textdatesand1or3
 fork,_inpairs(args)do
 iftype(k)=='number'then
 ifk>imaxthen
 invalid=tostring(k)
 break
 end
 else
 ifnotgood[k]then
 invalid=k
 break
 end
 end
 end
 ifinvalidthen
 result=result..message('mt-warn-param1',invalid)
 end
 end
 returnresult
 end

 localfunctiondda(frame)
 -- Implement [[Template:Death date and age]].
 localargs=frame:getParent().args
 ifisFake(args)then
 return''
 end
 localoptions={
 missing1='mt-need-valid-dd',
 missing2='mt-need-valid-bd2',
 noMissing=true,
 partial=true,
 }
 localdate1,date2=getDates(frame,options)
 iftype(date1)=='string'then
 returndate1
 end
 localdiff=date1-date2
 ifdiff.isnegativethen
 returnmessage('mt-dd-wrong-order')
 end
 localDate=getExports(frame)
 localtoday=Date('currentdate')+1-- one day in future allows for timezones
 ifdate1>todaythen
 returnmessage('mt-dd-future')
 end
 localyears
 ifdiff.partialthen
 years=diff.partial.years
 years=type(years)=='table'andyears[2]oryears
 else
 years=diff.years
 end
 ifyears>MAX_AGEthen
 returnmessage('mt-invalid-dates-age')
 end
 localfmt_date,fmt_ymd,problem
 ifdate1.daythen-- y, m, d known
 problem,fmt_date=dateFormat(args)
 fmt_ymd='%-Y-%m-%d'
 elseifdate1.monththen-- y, m known; d unknown
 fmt_date='%B %-Y'
 fmt_ymd='%-Y-%m-00'
 else-- y known; m, d unknown
 fmt_date='%-Y'
 fmt_ymd='%-Y-00-00'
 end
 localsortKey
 localsortable=translateParameters.sortable[args.sortable]
 ifsortablethen
 localvalue=(date1.partialanddate1.partial.firstordate1).jdz
 sortKey=makeSort(value,sortable)
 end
 localresult=(sortKeyor'')..substituteParameters(
 mtext['txt-dda'],
 date1:text(fmt_ymd),
 from_en(date1:text(fmt_date)),
 from_en(dateDifference({
 diff=diff,
 show='y',
 abbr='abbr_off',
 disp=mtext['txt-dda-disp'],
 range='dash',
 sep='sep_space',
 }))
 )..(problemor'')
 localwarnings=tonumber(frame.args.warnings)
 ifwarningsandwarnings>0then
 localgood={
 df=true,
 mf=true,
 }
 localinvalid
 localimax=options.textdatesand2or6
 fork,_inpairs(args)do
 iftype(k)=='number'then
 ifk>imaxthen
 invalid=tostring(k)
 break
 end
 else
 ifnotgood[k]then
 invalid=k
 break
 end
 end
 end
 ifinvalidthen
 result=result..message('mt-warn-param1',invalid)
 end
 end
 returnresult
 end

 localfunctiondateToGsd(frame)
 -- Implement [[Template:Gregorian serial date]].
 -- Return Gregorian serial date of the given date, or the current date.
 -- The returned value is negative for dates before 1 January 1 AD
 -- despite the fact that GSD is not defined for such dates.
 localdate=getDates(frame,{wantMixture=true,single=true})
 iftype(date)=='string'then
 returndate
 end
 returntostring(date.gsd)
 end

 localfunctionjdToDate(frame)
 -- Return formatted date from a Julian date.
 -- The result includes a time if the input includes a fraction.
 -- The word 'Julian' is accepted for the Julian calendar.
 localDate=getExports(frame)
 localargs=frame:getParent().args
 localdate=Date('juliandate',args[1],args[2])
 ifdatethen
 returnfrom_en(date:text())
 end
 returnmessage('mt-need-jdn')
 end

 localfunctiondateToJd(frame)
 -- Return Julian date (a number) from a date which may include a time,
 -- or the current date ('currentdate') or current date and time ('currentdatetime').
 -- The word 'Julian' is accepted for the Julian calendar.
 localDate=getExports(frame)
 localargs=frame:getParent().args
 localdate=Date(args[1],args[2],args[3],args[4],args[5],args[6],args[7])
 ifdatethen
 returntostring(date.jd)
 end
 returnmessage('mt-need-valid-ymd-current')
 end

 localfunctiontimeInterval(frame)
 -- Implement [[Template:Time interval]].
 -- There are two positional arguments: date1, date2.
 -- The default for each is the current date and time.
 -- Result is date2 - date1 formatted.
 localDate=getExports(frame)
 localargs=frame:getParent().args
 localparms={
 extra=makeExtra(args),
 wantDuration=yes[args.duration],
 range=yes[args.range]or(args.range=='dash'and'dash'ornil),
 wantSc=yes[args.sc],
 }
 localfix=yes[args.fix]and'fix'or''
 localdate1=Date(fix,'partial',stripToNil(args[1])or'currentdatetime')
 ifnotdate1then
 returnmessage('mt-invalid-start')
 end
 localdate2=Date(fix,'partial',stripToNil(args[2])or'currentdatetime')
 ifnotdate2then
 returnmessage('mt-invalid-end')
 end
 parms.diff=date2-date1
 forargname,translateinpairs(translateParameters)do
 localparm=stripToNil(args[argname])
 ifparmthen
 parm=translate[parm]
 ifparm==nilthen-- test for nil because false is a valid setting
 returnmessage('mt-bad-param2',argname,args[argname])
 end
 parms[argname]=parm
 end
 end
 ifparms.roundthen
 localround=parms.round
 localshow=parms.show
 ifround~='on'then
 ifshowthen
 ifshow.id~=roundthen
 returnmessage('mt-conflicting-show',args.show,args.round)
 end
 else
 parms.show=translateParameters.show[round]
 end
 end
 parms.round=true
 end
 returnfrom_en(dateDifference(parms))
 end

 localfunctiontemplateGeneric(frame)
 localname=frame.args.template
 ifnotnamethen
 returnmessage('mt-template-x')
 end
 returnageGeneric(frame:newChild{title=mw.title.new(name,10),args=frame.args})
 end

 return{
 age_generic=ageGeneric,-- can emulate several age templates
 birth_date_and_age=bda,-- Template:Birth_date_and_age
 death_date_and_age=dda,-- Template:Death_date_and_age
 gsd=dateToGsd,-- Template:Gregorian_serial_date
 extract=dateExtract,-- Template:Extract
 jd_to_date=jdToDate,-- Template:?
 JULIANDAY=dateToJd,-- Template:JULIANDAY
 time_interval=timeInterval,-- Template:Time_interval
 ['']=templateGeneric,-- same as age_generic, but can be invoked directly
 }

AltStyle によって変換されたページ (->オリジナル) /