Modulo:Complex date: differenze tra le versioni

Vai alla navigazione Vai alla ricerca
nessun oggetto della modifica
(update from sandbox (commons version))
 
Nessun oggetto della modifica
Riga 1: Riga 1:
--[[
--[[  
   __  __          _      _        ____                      _                _
   __  __          _      _        ____                      _                _       _     
  |  \/  | ___  __| |_  _| | ___ _ / ___|___  _ __ ___  _ __ | | _____  __  __| | __ _| |_ ___  
  |  \/  | ___  __| |_  _| | ___ _ / ___|___  _ __ ___  _ __ | | _____  __  __| | __ _| |_ ___  
  | |\/| |/ _ \ / _` | | | | |/ _ (_) |  / _ \| '_ ` _ \| '_ \| |/ _ \ \/ /  / _` |/ _` | __/ _ \
  | |\/| |/ _ \ / _` | | | | |/ _ (_) |  / _ \| '_ ` _ \| '_ \| |/ _ \ \/ /  / _` |/ _` | __/ _ \
  | |  | | (_) | (_| | |_| | |  __/_| |__| (_) | | | | | | |_) | |  __/>  <  | (_| | (_| | ||  __/
  | |  | | (_) | (_| | |_| | |  __/_| |__| (_) | | | | | | |_) | |  __/>  <  | (_| | (_| | ||  __/
  |_|  |_|\___/ \__,_|\__,_|_|\___(_)\____\___/|_| |_| |_| .__/|_|\___/_/\_\  \__,_|\__,_|\__\___|
  |_|  |_|\___/ \__,_|\__,_|_|\___(_)\____\___/|_| |_| |_| .__/|_|\___/_/\_\  \__,_|\__,_|\__\___|
                                                         |_|
                                                         |_|                                    
 
This module is intended for creation of complex date phrases in variety of languages.
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
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.
at Module:Complex date/sandbox/testcases.
 
Authors and maintainers:
Authors and maintainers:
* User:Sn1per - first draft of the original version
* User:Sn1per - first draft of the original version  
* User:Jarekt - corrections and expansion of the original version
* User:Jarekt - corrections and expansion of the original version  
]]
]]


Riga 21: Riga 21:
local i18n      = require('Module:i18n/complex date')  -- used for translations of date related phrases
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 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


-- ==================================================
-- ==================================================
-- === Internal functions ===========================
-- === Internal functions ===========================
-- ==================================================
-- ==================================================
local function formatError(msg, ...)
return string.format(
'<strong class="error">Error in [[Module:Complex date]]: ' ..
msg .. '</strong>', ...)
end


local function langSwitch(list,lang)
local function langSwitch(list, lang)
local langList = mw.language.getFallbacksFor(lang)
local langList = mw.language.getFallbacksFor(lang)
table.insert(langList,1,lang)
table.insert(langList, 1, lang)
table.insert(langList,math.max(#langList,2),'default')
table.insert(langList, math.max(#langList, 2), 'default')
for i,language in ipairs(langList) do
for i,language in ipairs(langList) do
if list[language] then
if list[language] then
Riga 38: Riga 44:
end
end


-- ==================================================
-- formatNum1() mostly require('Module:Formatnum').formatNum function used to
-- translate a number to use different numeral characters, except that it
-- does not call that function unless the language is on the list "LList".
local LList = {
ar = 1,
arq = 1,
ary = 1,
arz = 1,
bn = 1,
bo = 1,
bpy = 1,
ckb = 1,
fa = 1,
glk = 1,
gu = 1,
hi = 1,
kn = 1,
ks = 1,
lo = 1,
['ml-old'] = 1,
mn = 1,
mr = 1,
mzn = 1,
new = 1,
['or'] = 1,
pa = 1,
ps = 1,
sd = 1,
si = 1,
te = 1,
th = 1,
ur = 1,
}
local function formatnum1(numStr, lang)
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
if LList[lang] then -- call only when the language is on the list
numStr = require('Module:Formatnum').formatNum(numStr, lang, 1)
numStr = formatnum(numStr, lang, 1)
end
end
return numStr
return numStr
end
end


-- ==================================================
local function getISODate(datestr, datetype, lang, num, case)
local function getISODate(datestr, datetype, lang, num, case)
-- translate dates in the format YYYY, YYYY-MM, and YYYY-MM-DD
-- translate dates in the format YYYY, YYYY-MM, and YYYY-MM-DD
Riga 55: Riga 89:
-- look up the grammatical case needed and call ISOdate module
-- look up the grammatical case needed and call ISOdate module
local rec = langSwitch(i18n.Translations[datetype], lang)
local rec = langSwitch(i18n.Translations[datetype], lang)
if type(rec)=='table' then
if type(rec) == 'table' then
case = rec.case[num]
case = rec.case[num]
end
end
Riga 62: Riga 96:
end
end


-- =======================================================================
local function translatePhrase(date1, date2, operation, lang, state)
local function translatePhrase(date1, date2, operation, lang, state)
-- use tables in Module:i18n/complex date to translate a phrase
-- use tables in Module:i18n/complex date to translate a phrase
if not i18n.Translations[operation] then
if not i18n.Translations[operation] then
p.Error = string.format('<span style="background-color:red;">Error in [[Module:Complex date]]: input parameter "%s" is not recognized.</span>', operation or 'nil')
p.Error = formatError('input parameter "%s" is not recognized.', operation or 'nil')
return ''
return ''
end
end
local dateStr = langSwitch(i18n.Translations[operation], lang)
local dateStr = langSwitch(i18n.Translations[operation], lang)
if type(dateStr)=='table' then
if type(dateStr) == 'table' then
dateStr = dateStr[1]
dateStr = dateStr[1]
end
end
if type(dateStr)=='function' then
if type(dateStr) == 'function' then
local dateFunc = dateStr
local success
local nDates = i18n.Translations[operation]['nDates']
local nDates = i18n.Translations[operation]['nDates']
if nDates==2 then -- 2 date phrase
if nDates == 2 then -- double dated phrase
dateStr = dateFunc(date1, date2, state)
success, dateStr = pcall(dateStr, date1, date2, state)
else -- 1 date phrase
else -- single dated phrase
dateStr = dateFunc(date1, state)
success, dateStr = pcall(dateStr, date1, state)
end
end
end
end
if type(dateStr) == 'string' then
if type(dateStr)=='string' then
-- replace parts of the string '$date1' and '$date2' with date1 and date2 strings
-- replace parts of the string '$date1' and '$date2' with date1 and date2 strings
dateStr = mw.ustring.gsub(dateStr, '$date1', date1)
dateStr = mw.ustring.gsub(dateStr, '$date1', date1)
Riga 96: Riga 128:
end
end


-- =======================================================================
local function oneDatePhrase(dateStr, adj, era, units, lang, num, case, state)
local function oneDatePhrase(dateStr, adj, era, units, lang, num, case, state)
-- translate a single date phrase
-- translate a single date phrase
if num==2 then
if num == 2 then
state.adj, state.era, state.units, state.precision = state.adj2, state.era2, state.units2, state.precision2
state.adj, state.era, state.units, state.precision = state.adj2, state.era2, state.units2, state.precision2  
end
end
-- dateStr can have many forms: ISO date, year or a number for  
-- dateStr can have many forms: ISO date, year or a number for
-- decade, century or millennium
-- decade, century or millennium
if units == '' then -- unit is "year", "month", "day"
if units == '' then -- unit is "year", "month", "day"
Riga 110: Riga 140:
dateStr = translatePhrase(dateStr, '', units, lang, state)
dateStr = translatePhrase(dateStr, '', units, lang, state)
end
end
-- add adjective ("early", "mid", etc.) or preposition ("before", "after",  
-- add adjective ("early", "mid", etc.) or preposition ("before", "after",
-- "circa", etc.) to the date
-- "circa", etc.) to the date
if adj ~= '' then
if adj ~= '' then
Riga 118: Riga 147:
dateStr = formatnum1(dateStr, lang)
dateStr = formatnum1(dateStr, lang)
end
end
-- add era
-- add era
if era ~= '' then
if era ~= '' then
Riga 126: Riga 154:
end
end


-- =======================================================================
local function twoDatePhrase(date1, date2, state, lang)
local function twoDatePhrase(date1, date2, state, lang)
-- translate a double date phrase
-- translate a double date phrase
local dateStr, case
local dateStr, case
local era=''
local era = ''
if state.era1 == state.era2 then
if state.era1 == state.era2 then
-- if both eras are the same than add it only once
-- if both eras are the same than add it only once
Riga 153: Riga 180:
end
end


-- =======================================================================
local function otherPhrases(date1, date2, operation, era, lang, state)
local function otherPhrases(date1, date2, operation, era, lang, state)
-- translate specialized phrases
-- translate specialized phrases
local dateStr = ''
local dateStr = ''
if operation == 'islamic' then
if operation == 'islamic' then
if date2=='' then date2 = mw.getCurrentFrame():callParserFunction('#time', 'xmY', date1) end
if date2 == '' then
date2 = mw.getCurrentFrame():callParserFunction('#time', 'xmY', date1)
end
date1 = getISODate(date1, operation, lang, 1, nil)
date1 = getISODate(date1, operation, lang, 1, nil)
date2 = getISODate(date2, operation, lang, 2, nil)
date2 = getISODate(date2, operation, lang, 2, nil)
if era == '' then era = 'ad' end
if era == '' then era = 'ad' end
dateStr = translatePhrase(date1, '', era, lang, state) .. ' (' .. translatePhrase(date2, '', 'ah', lang, state) .. ')'
dateStr = translatePhrase(date1, '', era, lang, state)
.. ' (' .. translatePhrase(date2, '', 'ah', lang, state) .. ')'
era = ''
era = ''
elseif operation == 'julian' then
elseif operation == 'julian' then
if not date2 and date1 then -- Convert from Julian to Gregorian calendar date
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)
local JDN = Calendar._date2jdn(date1, 0)
if JDN then
if JDN then
Riga 179: Riga 204:
date2 = getISODate(date2, operation, lang, 2, nil)
date2 = getISODate(date2, operation, lang, 2, nil)
dateStr = translatePhrase(date1, date2, operation, lang, state)
dateStr = translatePhrase(date1, date2, operation, lang, state)
dateStr = mw.ustring.gsub(mw.ustring.gsub(dateStr, '%( ', '('), ' %)', ')') -- in case date2 is empty
dateStr = dateStr.gsub('%( ', '(').gsub(' %)', ')') -- in case date2 is empty
elseif operation == 'turn of the year' or operation == 'turn of the decade' or operation == 'turn of the century' then
elseif operation == 'turn of the year'
local dt = 1
or operation == 'turn of the decade'
if operation == 'turn of the decade' then dt=10 end
or operation == 'turn of the century' then  
if not date2 or date2=='' then date2=tostring(tonumber(date1)-dt) end
if not date2 or date2 == '' then
if era~='bp' and era~='bc' then date1, date2 = date2, date1 end
local dt = (operation == 'turn of the decade') and 10 or 1
date2 = tostring(tonumber(date1) - dt)
end
if era ~= 'bp' and era ~= 'bc' then
date1, date2 = date2, date1
end
if operation == 'turn of the year' then
if operation == 'turn of the year' then
date1 = ISOdate(date1, lang, '', '', 1)
date1 = ISOdate(date1, lang, '', '', 1)
Riga 194: Riga 224:
dateStr = translatePhrase(date1, date2, operation, lang, state)
dateStr = translatePhrase(date1, date2, operation, lang, state)
elseif operation == 'year unknown' then
elseif operation == 'year unknown' then
dateStr = translatePhrase('', '', operation, lang, state) .. '<div style="display: none;">Unknown date</div>'
dateStr = translatePhrase('', '', operation, lang, state) .. '<q style="display:none">Unknown date</q>'
elseif operation == 'unknown' then
elseif operation == 'unknown' then
dateStr = tostring(mw.message.new( "exif-unknowndate" ):inLanguage( lang )) .. '<div style="display: none;">Unknown date</div>'
dateStr = tostring(mw.message.new("exif-unknowndate"):inLanguage(lang)) .. '<q style="display:none">Unknown date</q>'
end
end
-- add era
-- add era
if era ~= '' then
if era ~= '' then
Riga 206: Riga 235:
end
end


-- =======================================================================
local function checkAliases(str1, str2, sType)
local function checkAliases(str1, str2, sType)
-- some inputs have many aliases - reconcile them and ensure string is playing a proper role
-- some inputs have many aliases - reconcile them and ensure string is playing a proper role
local out = ''
local out = ''
if str1 and str1~='' then
if str1 and str1 ~= '' then
local a = i18n.Synonyms[str1] -- look up synonyms of "str1"
local a = i18n.Synonyms[str1] -- look up synonyms of "str1"
if a then
if a then
out = a[1]
out = a[1]
else
else
p.Error = string.format('<span style="background-color:red;">Error in [[Module:Complex date]]: %s is not recognized.</span>', str1)
p.Error = formatError('"%s" is not a recognized alias.', str1)
end
end
elseif str2 and str2~='' then -- if "str1" of type "sType" is empty than maybe ...
elseif str2 and str2 ~= '' then -- if "str1" of type "sType" is empty than maybe ...
local a = i18n.Synonyms[str2]   -- ..."str2" is of the same type and is not empty
local a = i18n.Synonyms[str2] -- ..."str2" is of the same type and is not empty
if a and a[2]==sType then
if a and a[2] == sType then
out  = a[1]
out  = a[1]
str2 = ''
str2 = ''
Riga 227: Riga 255:
end
end


-- =======================================================================
local function datePrecision(dateStr, units)
local function datePrecision(dateStr, units)
-- "in this module "Units" is a string like millennium, century, or decade
-- "in this module "Units" is a string like millennium, century, or decade
-- "precision" is wikibase compatible date precision number: 6=millennium, 7=century, 8=decade, 9=year, 10=month, 11=day
-- "precision" is wikibase compatible date precision number: 6=millennium, 7=century, 8=decade, 9=year, 10=month, 11=day
-- based on string or numeric input calculate "Units" and "precision"
-- based on string or numeric input calculate "Units" and "precision"
local precision
local precision
if type(units)=='number' then
local dateNum = tonumber(dateStr);
if type(units) == 'number' then
precision = units
precision = units
if precision>11 then precision=11 end -- clip the range of precision values
if precision > 11 then precision = 11 end -- clip the range of precision values
if    precision==6 then units='millennium'
if    precision == 6 then units = 'millennium'
elseif precision==7 then units='century'
elseif precision == 7 then units = 'century'
elseif precision==8 then units='decade'
elseif precision == 8 then units = 'decade'
else units = ''
else                       units = ''
end
end
elseif type(units)=='string' then
elseif type(units) == 'string' then
units = string.lower(units)
units = string.lower(units);
if    units=='millennium' then precision=6
if    units == 'millennium' then precision = 6
elseif units=='century'    then precision=7
elseif units == 'century'    then precision = 7
elseif units=='decade'    then precision=8
elseif units == 'decade'    then precision = 8
else precision=9
else                             precision = 9
end
end
end
end
if units=='' or precision==9 then
if units == ''
or precision == 9 then
local sLen = mw.ustring.len(dateStr)
local sLen = mw.ustring.len(dateStr)
if    sLen<= 4 then precision=9
if    sLen <= 4 then precision = 9
elseif sLen== 7 then precision=10
elseif sLen == 7 then precision = 10
elseif sLen>=10 then precision=11
elseif sLen >= 10 then precision = 11
end
end
units=''
units=''
end
end
if precision==6 and dateStr.match( dateStr, '%d000' )~=nil then
if precision == 6 and dateStr.match(dateStr, '%d000') ~= nil then  
dateStr = tostring(math.floor(tonumber(dateStr)/1000) +1)
dateStr = tostring(math.floor(tonumber(dateStr) / 1000) + 1)
elseif precision==7 and mw.ustring.match( dateStr, '%d%d00' )~=nil then
elseif precision == 7 and mw.ustring.match(dateStr, '%d%d00') ~= nil then
dateStr = tostring(math.floor(tonumber(dateStr)/100) +1)
dateStr = tostring(math.floor(tonumber(dateStr) / 100) + 1)
end
end
return dateStr, units, precision
return dateStr, units, precision
end
end


-- =======================================================================
local eraLUT = {
[''] = '+', ad = '+', bc = '-', bp = '-', -- Gregorian eras
ah = 1, -- TODO: islamic era not supported
}
local function isodate2timestamp(dateStr, precision, era)
local function isodate2timestamp(dateStr, precision, era)
-- convert date string to timestamps used by Quick Statements
-- convert date string to timestamps used by Quick Statements
local tStamp = nil
if precision < 6 then
if era == 'ah' or precision<6 then
return nil
return nil
elseif era ~= '' then
local eraLUT = {ad='+', bc='-', bp='-' }
era = eraLUT[era]
else
era='+'
end
end
 
era = eraLUT[era or '']
-- convert isodate to timestamp used by quick statements
if not era -- unknown era
if precision>=9 then
or era ~= '+' and era ~= '-' then -- non-Gregorian eras
if string.match(dateStr,"^%d%d%d%d$") then               -- if YYYY format
return nil -- TODO: convert dates from non-Gregorian eras
end
-- convert isodate to timestamp used by quick statements
local tStamp
if precision >= 9 then -- year or better
if string.match(dateStr,"^%d%d%d%d$") then -- if YYYY format  
tStamp = era .. dateStr .. '-00-00T00:00:00Z/9'
tStamp = era .. dateStr .. '-00-00T00:00:00Z/9'
elseif string.match(dateStr,"^%d%d%d%d%-%d%d$") then     -- if YYYY-MM format
elseif string.match(dateStr,"^%d%d%d%d%-%d%d$") then -- if YYYY-MM format  
tStamp = era .. dateStr .. '-00T00:00:00Z/10'
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
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'
tStamp = era .. dateStr .. 'T00:00:00Z/11'
end
end
elseif precision==8 then -- decade
elseif precision == 8 then -- decade
tStamp = era .. dateStr .. '-00-00T00:00:00Z/8'
tStamp = era .. dateStr .. '-00-00T00:00:00Z/8'
elseif precision==7 then -- century
elseif precision == 7 then -- century
local d = tostring(tonumber(dateStr)-1)
local d = tostring(tonumber(dateStr) - 1)
tStamp = era .. d .. '50-00-00T00:00:00Z/7'
tStamp = era .. d .. '50-00-00T00:00:00Z/7'
elseif precision==6 then
elseif precision == 6 then -- millenium
local d = tostring(tonumber(dateStr)-1)
local d = tostring(tonumber(dateStr) - 1)
tStamp = era .. d .. '500-00-00T00:00:00Z/6'
tStamp = era .. d .. '500-00-00T00:00:00Z/6'
end
end
return tStamp
return tStamp
end
end


-- =======================================================================
local yearQualifiers = {
early = 'Q40719727', mid = 'Q40719748', late = 'Q40719766',
firsthalf = 'Q40719687', secondhalf = 'Q40719707',
['1quarter'] = 'Q40690303', ['2quarter'] = 'Q40719649',
['3quarter'] = 'Q40719662', ['4quarter'] = 'Q40719674',
spring = 'Q40720559', summer = 'Q40720564',
autumn = 'Q40720568', winter = 'Q40720553'
}
local dayQualifiers = {
['from'] = 'P580', ['until'] = 'P582',
['after'] = 'P1319', ['before'] = 'P1326',
['by'] = 'P1326',
}
local function oneDateQScode(dateStr, adj, era, precision)
local function oneDateQScode(dateStr, adj, era, precision)
-- create QuickStatements string for "one date" dates
-- create QuickStatements string for "one date" dates
local outputStr = ''
local outputStr = ''
local d = isodate2timestamp(dateStr, precision, era)
local d = isodate2timestamp(dateStr, precision, era)
if not d then
if not d then
return ''
return ''
end
end
local rLUT = {            early='Q40719727'    , mid='Q40719748',     late='Q40719766',
local yearQ, dayQ = yearQualifiers[adj], dayQualifiers[adj]
['1quarter']='Q40690303' , ['2quarter']='Q40719649'  , ['3quarter']='Q40719662', ['4quarter']='Q40719674',
if adj == '' then
spring='Q40720559'  , summer='Q40720564'    , autumn='Q40720568'  , winter='Q40720553',
firsthalf='Q40719687', secondhalf='Q40719707' }
local qLUT = {['from']='P580', ['until']='P582', ['after']='P1319', ['before']='P1326', ['by']='P1326'}
 
local refine = rLUT[adj]
local qualitier = qLUT[adj]
 
if adj=='' then
outputStr = d
outputStr = d
elseif adj=='circa' then
elseif adj == 'circa' then
outputStr = d..",P1480,Q5727902"
outputStr = d .. ',P1480,Q5727902'
elseif refine then
elseif yearQ then
outputStr = d..",P4241,"..refine
outputStr = d .. ',P4241,' .. yearQ
elseif precision>7 and qualitier then
elseif dayQ and precision > 7 then
local century = string.gsub(d, 'Z%/%d+', 'Z/7')
local century = string.gsub(d, 'Z%/%d+', 'Z/7')
outputStr = century ..",".. qualitier ..","..d
outputStr = century .. ',' .. dayQ .. ',' .. d
end
end
return outputStr
return outputStr  
end
end


-- =======================================================================
local function twoDateQScode(date1, date2, state)
local function twoDateQScode(date1, date2, state)
-- create QuickStatements string for "two date" dates
-- create QuickStatements string for "two date" dates
if state.adj1~='' or state.adj2~='' or state.era1~=state.era2 then
if state.adj1 ~= ''
or state.adj2 ~= ''
or state.era1 ~= state.era2 then
return '' -- QuickStatements string are not generated for two date phrases with adjectives
return '' -- QuickStatements string are not generated for two date phrases with adjectives
end
end
Riga 341: Riga 374:
local d1 = isodate2timestamp(date1, state.precision1, state.era1)
local d1 = isodate2timestamp(date1, state.precision1, state.era1)
local d2 = isodate2timestamp(date2, state.precision2, state.era2)
local d2 = isodate2timestamp(date2, state.precision2, state.era2)
if (not d1) or (not d2) then
if not d1 or not d2 then
return ''
return ''
end
end
-- find date with lower precision in common to both dates
-- find date with lower precision in common to both dates
local cd
local cd
local year1 = tonumber(string.sub(d1,2,5))
local year1 = tonumber(string.sub(d1, 2, 5))
local year2 = tonumber(string.sub(d2,2,5))
local year2 = tonumber(string.sub(d2, 2, 5))
local k = 0
local k = 0
for i = 1,10,1 do
for i = 1, 10, 1 do  
if string.sub(d1,1,i)==string.sub(d2,1,i) then
if string.sub(d1, 1, i) == string.sub(d2, 1, i) then  
k = i -- find last matching letter
k = i -- find last matching letter
end
end
end
end
if k>=9 then             -- same month, since "+YYYY-MM-" is in common
if k >= 9 then               -- same month, since "+YYYY-MM-" is in common
cd = isodate2timestamp(string.sub(d1,2,8), 10, state.era1)
cd = isodate2timestamp(string.sub(d1, 2, 8), 10, state.era1)
elseif k>=6 and k<9 then -- same year, since "+YYYY-" is in common
elseif k >= 6 and k < 9 then -- same year, since "+YYYY-" is in common
cd = isodate2timestamp(tostring(year1), 9, state.era1)
cd = isodate2timestamp(tostring(year1), 9, state.era1)
elseif k==4 then         -- same decade(k=4, precision=8),  since "+YYY" is in common
elseif k == 4 then           -- same decade(k=4, precision=8),  since "+YYY" is in common
cd = isodate2timestamp(tostring(year1), 8, state.era1)
cd = isodate2timestamp(tostring(year1), 8, state.era1)
elseif k==3 then         -- same century(k=3, precision=7) since "+YY" is in common
elseif k == 3 then           -- same century(k=3, precision=7) since "+YY" is in common
  local d = tostring(math.floor(year1/100) +1) -- convert 1999 -> 20
  local d = tostring(math.floor(year1 / 100) + 1) -- convert 1999 -> 20
cd = isodate2timestamp( d, 7, state.era1)
cd = isodate2timestamp(d, 7, state.era1)
elseif k==2 then         -- same millennium (k=2, precision=6),  since "+Y" is in common
elseif k == 2 then           -- same millennium (k=2, precision=6),  since "+Y" is in common
local d = tostring(math.floor(year1/1000) +1) -- convert 1999 -> 2
local d = tostring(math.floor(year1 / 1000) + 1) -- convert 1999 -> 2
cd = isodate2timestamp( d, 6, state.era1)
cd = isodate2timestamp(d, 6, state.era1)
end
end
if not cd then
if not cd then
Riga 371: Riga 404:
end
end
--if not cd then
--if not cd then
-- return ' <br/>error: ' .. d1.." / " .. d2.." / ".. (cd or '') .." / ".. string.sub(d1,2,5).." / " .. string.sub(d2,2,5).." / " .. tostring(k)
-- return formatError(d1 .. ' / ' .. d2 .. ' / ' .. (cd or '')
-- .. ' / ' .. string.sub(d1, 2, 5) .. ' / ' .. string.sub(d2, 2, 5)
-- .. ' / ' .. tostring(k))
--end
--end
 
if state.conj == 'from-until'
--
or state.conj == 'and' and year1 == year2 - 1 then
if (state.conj=='from-until') or (state.conj=='and' and year1==year2-1) then
outputStr = cd .. ',P580,' .. d1 .. ',P582,' .. d2
outputStr = cd ..",P580,".. d1 ..",P582,".. d2
elseif state.conj == 'between'
elseif (state.conj=='between') or (state.conj=='or' and year1==year2-1) then
or state.conj == 'or' and year1 == year2 - 1 then
outputStr = cd ..",P1319,".. d1 ..",P1326,".. d2
outputStr = cd .. ',P1319,' .. d1 .. ',P1326,' .. d2
elseif state.conj=='circa2' then
elseif state.conj == 'circa2' then
outputStr = cd ..",P1319,".. d1 ..",P1326,".. d2 ..",P1480,Q5727902"
outputStr = cd .. ',P1319,' .. d1 .. ',P1326,' .. d2 .. ',P1480,Q5727902'
end
end
return outputStr
return outputStr
end
end


-- =======================================================================
-- ==================================================
local function processInputParams(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, lang, passNr)
-- === External functions ===========================
-- ==================================================


function p.Era(frame)
    -- process inputs
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']
local dateStr = args['date'] or ''
local eraType = string.lower(args['era']  or '')
dateStr = ISOdate(dateStr, lang, '', '', 1)
if eraType then
eraType = checkAliases(eraType , '', 'e')
dateStr = translatePhrase(dateStr, '', eraType, lang, {})
end
return dateStr
end
function p._complex_date(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, lang, passNr)
local Output = ''
-- process inputs and save date in state array
-- process inputs and save date in state array
local state  = {}
local state  = {}  
state.conj  = string.lower(conj  or '')
state.conj  = string.lower(conj  or '')
state.adj1  = string.lower(adj1  or '')
state.adj1  = string.lower(adj1  or '')
Riga 398: Riga 453:
state.units1 = string.lower(units1 or '')
state.units1 = string.lower(units1 or '')
state.units2 = string.lower(units2 or '')
state.units2 = string.lower(units2 or '')
-- if date 1 is missing but date 2 is provided than swap them
-- if date 1 is missing but date 2 is provided than swap them
if date1 == '' and date2 ~= '' then
if date1 == '' and date2 ~= '' then
date1 = date2
date1 = date2
date2 = ''
date2 = ''
state = {adj1 = state.adj2, era1 = state.era2, units1 = state.units2,  
state = {
        adj2 = '',        era2 = '',        units2 = '', conj=state.conj, num=1}
adj1 = state.adj2, era1 = state.era2, units1 = state.units2,  
    adj2 = '',        era2 = '',        units2 = '',
    conj = state.conj, num = 1}
end
end
if    date2 ~= '' then state.nDates = 2
if    date2 ~= '' then state.nDates = 2  
elseif date1 ~= '' then state.nDates = 1
elseif date1 ~= '' then state.nDates = 1  
else                   state.nDates = 0
else                 state.nDates = 0
end
end
-- reconcile alternative names for text inputs
-- reconcile alternative names for text inputs
local conj        = checkAliases(state.conj ,''  ,'j')
local conj        = checkAliases(state.conj ,''  ,'j')
Riga 422: Riga 477:
state.conj        = conj
state.conj        = conj
state.lang        = lang
state.lang        = lang
if p.Error~=nil then
if p.Error ~= nil then
return nil
return nil
end
end
-- calculate date precision value
-- calculate date precision value
date1, state.units1, state.precision1 = datePrecision(date1, state.units1)
date1, state.units1, state.precision1 = datePrecision(date1, state.units1)
date2, state.units2, state.precision2 = datePrecision(date2, state.units2)
date2, state.units2, state.precision2 = datePrecision(date2, state.units2)
 
-- Handle special cases  
-- Handle special cases
-- Some complex phrases can be created out of simpler ones. Therefore on pass 1 we try to create  
-- 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 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
-- the phrase out of the simpler ones
if passNr==1 then
if passNr == 1 then
if state.adj1=='circa' and state.nDates == 2 then
if state.nDates == 2 and state.adj1 == 'circa' then
state.conj = 'circa2'
state.conj = 'circa2'
state.adj1 = ''
state.adj1 = ''
state.adj2 = ''
state.adj2 = ''
end
end
if state.nDates == 2 and state.adj1=='late' and state.adj2=='early' and state.conj=='and'
if state.nDates == 2
and state.units1==state.units2 and state.era1==state.era2 then
and state.conj == 'and'
if state.units1=='century' then
and state.adj1 == 'late' and state.adj2 == 'early'
state.conj='turn of the century'
and state.units1 == state.units2 and state.era1 == state.era2 then
elseif state.units1=='decade' then
if     state.units1 == 'century' then state.conj = 'turn of the century'
state.conj='turn of the decade'
elseif state.units1 == 'decade' then state.conj = 'turn of the decade'
elseif state.units1=='' then
elseif state.units1 == ''       then state.conj = 'turn of the year'
state.conj='turn of the year'
end
end
state.adj1 = ''
state.adj1 = ''
Riga 455: Riga 507:
end
end
end
end
state.adj, state.era, state.units, state.precision = state.adj1, state.era1, state.units1, state.precision1
return date1, date2, state
end
-- ==================================================
-- === External functions ===========================
-- ==================================================
function p.Era(frame)
-- process inputs
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']
local dateStr = args['date'] or ''
local eraType = string.lower(args['era']  or '')
dateStr = ISOdate(dateStr, lang, '', '', 1)
if eraType then
eraType = checkAliases(eraType ,'','e')
dateStr = translatePhrase(dateStr, '', eraType, lang, {})
end
return dateStr
end
-- =======================================================================
function p._complex_date(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, lang, passNr)
local Output=''
local state
-- 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
end
local errorStr = string.format(
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',
'\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.conj, state.adj1, state.era1, state.units1, state.precision1,
  state.adj2, state.era2, state.units2, state.precision2, state.special)
state.adj2, state.era2, state.units2, state.precision2, state.special)
 
-- Call specialized functions
-- call specialized functions
local QScode = ''
local QScode = ''
if state.special~='' then
if state.special ~= '' then
Output = otherPhrases(date1, date2, state.special, state.era1, lang, state)
Output = otherPhrases(date1, date2, state.special, state.era1, lang, state)
elseif state.conj~='' then
elseif state.conj ~= '' then
QScode = twoDateQScode(date1, date2, state)
QScode = twoDateQScode(date1, date2, state)
Output = twoDatePhrase(date1, date2, state, lang)
Output = twoDatePhrase(date1, date2, state, lang)
elseif state.adj1~='' or state.era1~='' or state.units1~='' then
elseif state.adj1 ~= ''
or state.era1 ~= ''
or state.units1 ~= '' then
Output = oneDatePhrase(date1, state.adj1, state.era1, state.units1, lang, 1, nil, state)
Output = oneDatePhrase(date1, state.adj1, state.era1, state.units1, lang, 1, nil, state)
QScode = oneDateQScode(date1, state.adj1, state.era1, state.precision1)
QScode = oneDateQScode(date1, state.adj1, state.era1, state.precision1)
elseif date1~='' then
elseif date1 ~= '' then
Output = ISOdate(date1, lang, '', 'dtstart', '100-999')
Output = ISOdate(date1, lang, '', 'dtstart', '100-999')
end
end
if p.Error~=nil then
if p.Error ~= nil then
return errorStr
return errorStr
end
end
-- if there is any wikicode in the string than execute it
-- if there is any wikicode in the string than execute it
if mw.ustring.find(Output, '{') then
if mw.ustring.find(Output, '{') then
Riga 521: Riga 534:
end
end
if QScode and #QScode>0 then
if QScode and #QScode>0 then
QScode = ' <div style="display: none;">date QS:P,' .. QScode .. '</div>'
QScode = '<q style="display:none">date QS:P,' .. QScode .. '</q>'
end
end
return Output .. QScode
return Output .. QScode
end
end


-- =======================================================================
local certaintyQualifiers = {
circa      = 'Q5727902',
presumably = 'Q18122778',
possibly  = 'Q30230067',
probably  = 'Q56644435',
}
function p._complex_date_cer(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, certainty, lang)
function p._complex_date_cer(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, certainty, lang)
-- same as p._complex_date but with extra parameter for certainty: probably, possibly, presumably, etc.
-- same as p._complex_date but with extra parameter for certainty: probably, possibly, presumably, etc.
local dateStr = p._complex_date(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, lang, 1)
local dateStr = p._complex_date(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, lang, 1)
certainty = checkAliases(certainty, conj, 'r')
certainty = checkAliases(certainty, conj, 'r')
local LUT = {probably='Q56644435',  presumably='Q18122778', possibly='Q30230067', circa='Q5727902' }
if certainty and certaintyQualifiers[certainty] then
if certainty and LUT[certainty] then
dateStr = translatePhrase(dateStr, '', certainty, lang, {})
local state  = {}
dateStr = dateStr.gsub(
date1, date2, state  = processInputParams(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, lang, 1)
'(%<%a+ style="display: ?none;?"%>date QS:P,[^%<]+)(%</%a+%>)',
dateStr = translatePhrase(dateStr, '', certainty, lang, state)
'%1,P1480,' .. certaintyQualifiers[certainty] .. '%2')
dateStr = string.gsub(dateStr, '(%<div style="display: none;"%>date QS:P,[^%<]+)(%</div%>)', '%1,P1480,' .. LUT[certainty] .. '%2' )
end
end
return dateStr
return dateStr
end
end


-- =======================================================================
function p.complex_date(frame)
function p.complex_date(frame)
-- process inputs
    -- process inputs
local dateStr
local dateStr, Error
local args  = frame.args
local args  = frame.args
if not (args.lang and mw.language.isSupportedLanguage(args.lang)) then
if not (args.lang and mw.language.isSupportedLanguage(args.lang)) then  
args.lang = frame:callParserFunction( "int", "lang" ) -- get user's chosen language
args.lang = frame:callParserFunction("int", "Lang") -- get user's chosen language
end
end
local date1  = args['date1'] or args['2'] or args['date'] or ''
local date1  = args['date1'] or args['2'] or args['date'] or ''
Riga 561: Riga 576:
local certainty = args['certainty']
local certainty = args['certainty']
local lang  = args['lang']
local lang  = args['lang']
dateStr = p._complex_date_cer(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, certainty, lang)
dateStr = p._complex_date_cer(conj, adj1, date1, units1, era1, adj2, date2, units2, era2, certainty, lang)
if p.Error~=nil then
if p.Error ~= nil then
dateStr = p.Error .. '[[Category:Pages using Complex date template with incorrect parameter]]'
dateStr = p.Error .. '[[Category:Pages using Complex date template with incorrect parameter]]'
end
end
Utente anonimo

Menu di navigazione