Module:Complex date/sandbox: Difference between revisions

Content deleted Content added
adjust whitespaces
No edit summary
 
(4 intermediate revisions by the same user not shown)
Line 9:
This module is intended for creation of complex date phrases in variety of languages.
 
Once deployed, please do not modify this code without applying the changes first at Module:Complex date/sandbox and testing
at Module:Complex date/sandbox/testcases.
 
Authors and maintainers:
* User:Sn1per - first draft of the original version
* User:Jarekt - corrections and expansion of the original version
]]
 
Line 21:
local i18n = require('Module:i18n/complex date') -- used for translations of date related phrases
local ISOdate = require('Module:ISOdate')._ISOdate -- used for parsing dates in YYYY-MM-DD and related formats
local Calendar -- loaded lazily
local formatnum = require('Module:Formatnum').formatNum -- used for translation into other alphabets
local Calendar = require('Module:Calendar') -- used for conversions between Julian and Gregorian calendar dates
 
-- ==================================================
Line 41 ⟶ 40:
-- ==================================================
local function formatnum1(numStr, lang)
-- mostly require('Module:Formatnum').formatNum function used to translate a number to use different numeral characters,
-- except that it it does not call that function unless the language is on the list "LList"
local LList = {bn=1,bpy=1,kn=1,hi=1,mr=1,new=1,pa=1,gu=1,fa=1,glk=1,mzn=1,ur=1,ar=1,ckb=1,ks=1,lo=1,['or']=1,bo=1,['ml-old']=1,mn=1,te=1,th=1}
if LList[lang] then -- call only when the language is on the list
numStr = formatnumrequire('Module:Formatnum').formatNum(numStr, lang, 1)
end
return numStr
Line 101 ⟶ 100:
-- translate a single date phrase
if num==2 then
state.adj, state.era, state.units, state.precision = state.adj2, state.era2, state.units2, state.precision2
end
-- dateStr can have many forms: ISO date, year or a number for
-- decade, century or millennium
if units == '' then -- unit is "year", "month", "day"
Line 112 ⟶ 111:
end
-- add adjective ("early", "mid", etc.) or preposition ("before", "after",
-- "circa", etc.) to the date
if adj ~= '' then
Line 168 ⟶ 167:
elseif operation == 'julian' then
if not date2 and date1 then -- Convert from Julian to Gregorian calendar date
if Calendar == nil then
Calendar = require("Module:Calendar") -- lazy loding (only if needed)
end
local JDN = Calendar._date2jdn(date1, 0)
if JDN then
Line 178 ⟶ 180:
dateStr = translatePhrase(date1, date2, operation, lang, state)
dateStr = mw.ustring.gsub(mw.ustring.gsub(dateStr, '%( ', '('), ' %)', ')') -- in case date2 is empty
elseif operation == 'turn of the year' or operation == 'turn of the decade' or operation == 'turn of the century' then
local dt = 1;
if operation == 'turn of the decade' then dt=10 end
if not date2 or date2=='' then date2=tostring(tonumber(date1)-dt) end
Line 231 ⟶ 233:
-- based on string or numeric input calculate "Units" and "precision"
local precision
local dateNum = tonumber(dateStr);
if type(units)=='number' then
precision = units
Line 241 ⟶ 242:
end
elseif type(units)=='string' then
units = string.lower(units);
if units=='millennium' then precision=6
elseif units=='century' then precision=7
Line 256 ⟶ 257:
units=''
end
if precision==6 and dateStr.match( dateStr, '%d000' )~=nil then
dateStr = tostring(math.floor(tonumber(dateStr)/1000) +1)
elseif precision==7 and mw.ustring.match( dateStr, '%d%d00' )~=nil then
Line 279 ⟶ 280:
 
-- convert isodate to timestamp used by quick statements
if precision>=9 then
if string.match(dateStr,"^%d%d%d%d$") then -- if YYYY format
tStamp = era .. dateStr .. '-00-00T00:00:00Z/9'
elseif string.match(dateStr,"^%d%d%d%d%-%d%d$") then -- if YYYY-MM format
tStamp = era .. dateStr .. '-00T00:00:00Z/10'
elseif string.match(dateStr,"^%d%d%d%d%-%d%d%-%d%d$") then -- if YYYY-MM-DD format
tStamp = era .. dateStr .. 'T00:00:00Z/11'
end
Line 342 ⟶ 343:
if (not d1) or (not d2) then
return ''
end
-- find date with lower precision in common to both dates
local cd
Line 349 ⟶ 350:
local k = 0
for i = 1,10,1 do
if string.sub(d1,1,i)==string.sub(d2,1,i) then
k = i -- find last matching letter
end
Line 397 ⟶ 398:
state.units1 = string.lower(units1 or '')
state.units2 = string.lower(units2 or '')
 
-- if date 1 is missing but date 2 is provided than swap them
if date1 == '' and date2 ~= '' then
Line 405 ⟶ 406:
adj2 = '', era2 = '', units2 = '', conj=state.conj, num=1}
end
if date2 ~= '' then state.nDates = 2
elseif date1 ~= '' then state.nDates = 1
else state.nDates = 0
end
 
-- reconcile alternative names for text inputs
local conj = checkAliases(state.conj ,'' ,'j')
Line 424 ⟶ 425:
return nil
end
 
-- calculate date precision value
date1, state.units1, state.precision1 = datePrecision(date1, state.units1)
date2, state.units2, state.precision2 = datePrecision(date2, state.units2)
 
-- Handle special cases
-- Some complex phrases can be created out of simpler ones. Therefore on pass # 1 we try to create
-- the phrase using complex phrase and if that is not found than on the second pass we try to build
-- the phrase out of the simpler ones
Line 439 ⟶ 440:
state.adj2 = ''
end
if state.nDates == 2 and state.adj1=='late' and state.adj2=='early' and state.conj=='and'
and state.units1==state.units2 and state.era1==state.era2 then
if state.units1=='century' then
Line 455 ⟶ 456:
end
 
state.adj, state.era, state.units, state.precision = state.adj1, state.era1, state.units1, state.precision1
return date1, date2, state
end
Line 467 ⟶ 468:
local dateStr
local args = frame.args
if not (args.lang and mw.language.isSupportedLanguage(args.lang)) then
args.lang = frame:callParserFunction( "int", "lang" ) -- get user's chosen language
end
local lang = args['lang']
Line 477 ⟶ 478:
if eraType then
eraType = checkAliases(eraType ,'','e')
dateStr = translatePhrase(dateStr, '', eraType, lang, {})
end
return dateStr
Line 488 ⟶ 489:
 
-- process inputs and save date in state array
date1, date2, state = processInputParams(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, lang, passNr)
if p.Error~=nil then
return nil
Line 494 ⟶ 495:
 
local errorStr = string.format(
'\n*conj=%s, adj1=%s, era1=%s, unit1=%s, prec1=%i, adj2=%s, era2=%s, unit2=%s, prec2=%i, special=%s',
state.conj, state.adj1, state.era1, state.units1, state.precision1,
state.adj2, state.era2, state.units2, state.precision2, state.special)
 
-- call specialized functions
local QScode = ''
if state.special~='' then
Output = otherPhrases(date1, date2, state.special, state.era1, lang, state)
elseif state.conj~='' then
QScode = twoDateQScode(date1, date2, state)
Line 534 ⟶ 535:
if certainty and LUT[certainty] then
local state = {}
date1, date2, state = processInputParams(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, lang, 1)
dateStr = translatePhrase(dateStr, '', certainty, lang, state)
dateStr = string.gsub(dateStr, '(%<div style="display: none;"%>date QS:P,[^%<]+)(%</div%>)', '%1,P1480,' .. LUT[certainty] .. '%2' )
Line 544 ⟶ 545:
function p.complex_date(frame)
-- process inputs
local dateStr, Error
local args = frame.args
if not (args.lang and mw.language.isSupportedLanguage(args.lang)) then
args.lang = frame:callParserFunction( "int", "lang" ) -- get user's chosen language
end
local date1 = args['date1'] or args['2'] or args['date'] or ''