Документација модула[прикажи] [уреди] [историја] [освежи]

This module has some functions to perform data calculations. It is not used directly from wikitext, but can be used by other lua modules. For age, a structure/table is used with the fields {years = x, days = y}.

Overview уреди

-- Returns age in years and days. Input is two dates in numeric form as returned from os.time
function ageInYearsAndDays(date2N, date1N)

-- Returns age in years, months and days. Input is two dates in numeric form as returned from os.time
function ageInYearsMonthsAndDays(date2N, date1N)

-- Returns < 0 if ageA < ageB, 0 if ageA == ageB, > 0 if ageA > ageB
function compareAges(ageA, ageB)

-- Returns true if ageA == ageB
function equalAges(ageA, ageB)

-- Returns a date as a sortable string with age in years and days ("x years and y days")
function ageInYearsAndDaysFormat(age)

== Example ==
<syntaxhighlight lang="lua">
local ageUtil = require('Module:Age utilities')
local ageInYearsAndDays = ageUtil.ageInYearsAndDays
local ageInYearsAndDaysFormat = ageUtil.ageInYearsAndDaysFormat

function something()
    local age = ageInYearsAndDays(os.time({year = 1997, month = 8, day = 4}), os.time({year = 1875, month = 2, day = 21}))
    return ageInYearsAndDaysFormat(age)
end

local p = {}

--------------------------------------------------------------------------------
-- Local helper functions
--------------------------------------------------------------------------------

-- Returns true if year is/was a leap year
local function isLeapYear(year)
	return year % 4 == 0 and (year % 100 ~= 0 or year % 400 == 0)
end

-- Copied from [[en:Module:Age]]
local function gsd(year, month, day)
	-- Return the Gregorian serial day (an integer >= 1) for the given date,
	-- or return nil if the date is invalid (only check that year >= 1).
	-- This is the number of days from the start of 1 AD (there is no year 0).
	-- This code implements the logic in [[Template:Gregorian serial date]].
	if year < 1 then
		return nil
	end
	local floor = math.floor
	local days_this_year = (month - 1) * 30.5 + day
	if month > 2 then
		if isLeapYear(year) then
			days_this_year = days_this_year - 1
		else
			days_this_year = days_this_year - 2
		end
		if month > 8 then
			days_this_year = days_this_year + 0.9
		end
	end
	days_this_year = floor(days_this_year + 0.5)
	year = year - 1
	local days_from_past_years = year * 365
		+ floor(year / 4)
		- floor(year / 100)
		+ floor(year / 400)
	return days_from_past_years + days_this_year
end

-- Returns the magnitude of a number defined as the integer part of log10 of the absolute value of the number
-- Equivalent to [[Mal:Magnitude]]
local function magnitude(number)
	if number == 0 then return nil end
	return math.floor(math.log10(math.abs(number)))
end

-- Returns a sorting key for a number
local function sortableNumber(number)
	local result = ''
	if number > 0 then
		result = result .. '3&' .. tostring(500 + magnitude(number))
	elseif number < 0 then
		result = result .. '1&' .. tostring(500 - magnitude(number))
	else -- 0
		result = result .. '2'
	end
	if number >= 0 then
		result = result .. '&' .. tostring(number)
	else -- negative
		result = result .. '&' .. tostring(100000 * (10 + number / 10 ^ magnitude(number)))
	end
	return '<span data-sort-value="' .. result .. '&">' .. tostring(number) .. '</span>';
end

--------------------------------------------------------------------------------
-- Functions for calculating age
--------------------------------------------------------------------------------

-- Returns age in years and days. Input is two dates in numeric form as returned from os.time
function p.ageInYearsAndDays(date2N, date1N)
	local date1 = os.date('!*t', date1N)
	local date2 = os.date('!*t', date2N)
	local age = {}
	
	age.years = date2.year - date1.year;
	if date2.month < date1.month or date2.month == date1.month and date2.day < date1.day then
		age.years = age.years - 1
	end
	
	local year = date2.year
	if date2.month < date1.month or date2.month == date1.month and date2.day < date1.day then
		year = year - 1
	end
	age.days = gsd(date2.year, date2.month, date2.day) - gsd(year, date1.month, date1.day)

	return age
end

--------------------------------------------------------------------------------
-- Functions for comparing ages
--------------------------------------------------------------------------------

-- Returns < 0 if ageA < ageB, 0 if ageA == ageB, > 0 if ageA > ageB
function p.compareAges(ageA, ageB)
	if ageA.years ~= ageB.years then
		if ageA.years < ageB.years then return -1 end
		return 1
	end
	if ageA.days ~= ageB.days then
		if ageA.days < ageB.days then return -1 end
		return 1
	end
	return 0 -- equal
end

-- Returns true if ageA == ageB
function p.equalAges(ageA, ageB)
	return p.compareAges(ageA, ageB) == 0
end


--------------------------------------------------------------------------------
-- Functions for displaying age
--------------------------------------------------------------------------------

-- Returns a date as a sortable string with age in years and days ("x år og y dager")
function p.ageInYearsAndDaysFormat(age)
	local result = sortableNumber(age.years) .. ' ' .. mw.getContentLanguage():plural(age.years, 'годинa', 'године', 'година')
	return result .. ', ' .. sortableNumber(age.days) .. ' ' .. mw.getContentLanguage():plural(age.days, 'дан', 'дана', 'дана')
end

return p