Module:Wikidata/Formatters/time
Εμφάνιση
Τεκμηρίωση module[δημιουργία] [ανανέωση]
--require "strict"
local p = {}
local lib = require 'Module:Wikidata/lib'
local i18n = mw.loadData('Module:Wikidata/i18n')
-- todo: move to lib
function p.yearDifference(sooner, later)
local age = later.year - sooner.year
if sooner.precision > 10 then
if later.precision > 10 then
if sooner.month > later.month then
age = age - 1
elseif sooner.month == later.month and sooner.day > later.day then
age = age - 1
end
return age, age
elseif later.precision == 10 then
if sooner.month == later.month then
return age - 1, age - 1 .. '–' .. age
end
if sooner.month > later.month then
age = age - 1
end
return age, age
end
elseif sooner.precision == 10 then
if later.precision > 9 then
if sooner.month == later.month then
return age - 1, age - 1 .. '–' .. age
end
if sooner.month > later.month then
age = age - 1
end
return age, age
end
end
return age - 1, age - 1 .. '–' .. age
end
-- todo: move to lib
function p.julianToGregorian(timevalue)
-- https://en.wikipedia.org/wiki/Gregorian_calendar#Difference_between_Gregorian_and_Julian_calendar_dates
local year = timevalue.year
local diff = math.floor(year / 100) - math.floor(year / 400) - 2
if year % 100 == 0 and year % 400 ~= 0 then
if timevalue.month == 2 and 30 - timevalue.day > diff then
diff = diff - 1
end
end
local feb_days
if year % 4 == 0 then
feb_days = 29
else
feb_days = 28
end
local days = { 31, feb_days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
local newvalue = mw.clone(timevalue)
newvalue.calendar = newvalue.CALENDAR.GREGORIAN
newvalue.day = newvalue.day + diff
if newvalue.day > days[newvalue.month] then
newvalue.day = newvalue.day - days[newvalue.month]
newvalue.month = newvalue.month + 1
if newvalue.month > 12 then
newvalue.month = 1
newvalue.year = newvalue.year + 1
end
end
return newvalue
end
local function stripZero(date, lang, timevalue)
-- odstraň nuly na začátku (rok < 1000 a > -1000)
local year
if timevalue.year > 0 then
year = math.abs(timevalue.year)
else
year = math.abs(timevalue.year) - 1
end
return mw.ustring.gsub(
date,
lang:formatNum(0) .. '+(' .. lang:formatNum(year, { noCommafy = true }) .. ')',
'%1'
)
end
function p.getRawValue(value, options)
local Time = require 'Module:Time'
return Time.newFromWikidataValue(value)
end
function p.formatRawValue(timevalue, options)
local lang = mw.getContentLanguage()
local precision = math.min(timevalue.precision, options.precision or timevalue.precision)
local timestring = tostring(timevalue)
local linked_app = ''
if not lib.IsOptionTrue(options, 'nolink') then
linked_app = '-linked'
end
local BCE_app = ''
if timevalue.year < 0 then
timestring = mw.ustring.sub(timestring, 2)
BCE_app = '-BCE'
end
local newstring
local map = {
[timevalue.PRECISION.KY] = 'millenium',
[timevalue.PRECISION.YEAR100] = 'century',
[timevalue.PRECISION.YEAR10] = 'decade',
[timevalue.PRECISION.YEAR] = 'year',
[timevalue.PRECISION.MONTH] = 'year-month',
[timevalue.PRECISION.DAY] = 'year-month-day',
}
if precision >= timevalue.PRECISION.YEAR then
local key = map[math.min(precision, timevalue.PRECISION.DAY)] .. BCE_app
local pattern = i18n.date[key .. linked_app] or i18n.date[key]
if precision > timevalue.PRECISION.MONTH
and timevalue.calendar == timevalue.CALENDAR.JULIAN
and timevalue > timevalue.newFromIso8601('1582-10-04')
then
local newvalue = p.julianToGregorian(timevalue)
local jul_pattern
if newvalue.year ~= timevalue.year then
jul_pattern = i18n.date['year-month-day']
elseif newvalue.month ~= timevalue.month then
jul_pattern = i18n.date['month-day']
else
jul_pattern = i18n.date.day
end
if newvalue.month == 2 and newvalue.day == 29 then
if year % 100 == 0 and year % 400 ~= 0 then
timevalue.year = 2000 -- hack to force formatting 29th February
end
end
newstring = mw.ustring.format('%s%s / %s%s',
stripZero(lang:formatDate(jul_pattern, timestring), lang, timevalue),
i18n.date.julian,
stripZero(lang:formatDate(pattern, tostring(newvalue)), lang, newvalue),
i18n.date.gregorian)
else
newstring = stripZero(lang:formatDate(pattern, timestring), lang, timevalue)
end
elseif precision >= timevalue.PRECISION.KY then
local key = map[precision] .. BCE_app
local coef = 10 ^ (9 - precision)
local number = math.floor(math.abs(timevalue.year) / coef)
if precision == timevalue.PRECISION.YEAR100 then
if timevalue.year % 100 > 0 and BCE_app == '' then
number = number + 1
end
elseif precision == timevalue.PRECISION.YEAR10 then
number = number * coef
end
newstring = mw.getCurrentFrame():preprocess(
mw.message.newRawMessage(i18n.date[key .. linked_app] or i18n.date[key])
:params(lang:formatNum(number, { noCommafy = true }))
:plain()
)
else
-- TODO
newstring = timestring
end
return newstring
end
function p.formatValue(value, options)
local timevalue = p.getRawValue(value, options)
local formatted = p.formatRawValue(timevalue, options)
if lib.IsOptionTrue(options, 'birthdate') and timevalue.precision >= timevalue.PRECISION.YEAR then
if #mw.wikibase.getBestStatements(options.id, 'P570') == 0 then
local Time = require 'Module:Time'
local age, age_text = p.yearDifference(timevalue, Time.new(os.date('!*t')))
formatted = mw.ustring.format('%s (%s)', formatted,
mw.getCurrentFrame():preprocess(
mw.message.newRawMessage(i18n.date.age)
:params(age_text)
:numParams(age)
:plain()
)
)
if age >= 100 then
formatted = formatted .. lib.category('centenarians-living')
elseif age < 0 then
formatted = formatted .. lib.category('failed-age-computing')
end
end
elseif lib.IsOptionTrue(options, 'deathdate') and timevalue.precision >= timevalue.PRECISION.YEAR then
local birthvalue
for _, statement in ipairs(mw.wikibase.getBestStatements(options.id, 'P569')) do
if lib.IsSnakValue(statement.mainsnak) then
local Formatters = require 'Module:Wikidata/Formatters'
birthvalue = Formatters.getRawValue(statement.mainsnak)
break
end
end
if birthvalue and birthvalue.precision >= birthvalue.PRECISION.YEAR then
local age, age_text = p.yearDifference(birthvalue, timevalue)
formatted = mw.ustring.format('%s (%s)', formatted,
mw.getCurrentFrame():preprocess(
mw.message.newRawMessage(i18n.date['in-the-age'])
:params(age_text)
:numParams(age)
:plain()
)
)
if age >= 100 then
formatted = formatted .. lib.category('centenarians')
end
end
end
return formatted
end
return p