Модул:Dts — разлика између измена
Пређи на навигацију
Пређи на претрагу
м (+) |
м (1 измена увезена) |
||
| (Нису приказане 2 међуизмене 2 корисника) | |||
| Ред 12: | Ред 12: | ||
Dts.months = { | Dts.months = { | ||
" | "januar", | ||
" | "februar", | ||
" | "mart", | ||
" | "april", | ||
" | "maj", | ||
" | "jun", | ||
" | "jul", | ||
" | "avgust", | ||
" | "septembar", | ||
" | "oktobar", | ||
" | "novembar", | ||
" | "decembar" | ||
} | } | ||
Dts.monthsAbbr = { | Dts.monthsAbbr = { | ||
" | "jan", | ||
" | "feb", | ||
" | "mar", | ||
" | "apr", | ||
" | "maj", | ||
" | "jun", | ||
" | "jul", | ||
" | "avg", | ||
" | "sep", | ||
" | "okt", | ||
" | "nov", | ||
" | "dec" | ||
} | } | ||
| Ред 50: | Ред 50: | ||
Dts.monthSearch = Dts._makeMonthSearch(Dts.months) | Dts.monthSearch = Dts._makeMonthSearch(Dts.months) | ||
Dts.monthSearchAbbr = Dts._makeMonthSearch(Dts.monthsAbbr) | Dts.monthSearchAbbr = Dts._makeMonthSearch(Dts.monthsAbbr) | ||
Dts.monthSearchAbbr[' | Dts.monthSearchAbbr['sept'] = 9 -- Allow "sept" to match septembar | ||
Dts.formats = { | Dts.formats = { | ||
| Ред 79: | Ред 79: | ||
if self.year then | if self.year then | ||
if self.year == 0 then | if self.year == 0 then | ||
error(' | error('godine ne mogu imati vrednost nula', 0) | ||
elseif self.year < -MAX_YEAR then | elseif self.year < -MAX_YEAR then | ||
error(string.format( | error(string.format( | ||
' | 'godine ne mogu imati vrednost manju od %s', | ||
lang:formatNum(-MAX_YEAR) | lang:formatNum(-MAX_YEAR) | ||
), 0) | ), 0) | ||
elseif self.year > MAX_YEAR then | elseif self.year > MAX_YEAR then | ||
error(string.format( | error(string.format( | ||
' | 'godine ne mogu imati vrednost veću od %s', | ||
lang:formatNum(MAX_YEAR) | lang:formatNum(MAX_YEAR) | ||
), 0) | ), 0) | ||
elseif math.floor(self.year) ~= self.year then | elseif math.floor(self.year) ~= self.year then | ||
error(' | error('godine moraju biti celi broj', 0) | ||
end | end | ||
end | end | ||
| Ред 99: | Ред 99: | ||
or math.floor(self.month) ~= self.month | or math.floor(self.month) ~= self.month | ||
) then | ) then | ||
error(' | error('meseci moraju biti celi broj iz intervala 1—12', 0) | ||
end | end | ||
if self.day and ( | if self.day and ( | ||
| Ред 106: | Ред 106: | ||
or math.floor(self.day) ~= self.day | or math.floor(self.day) ~= self.day | ||
) then | ) then | ||
error(' | error('dani moraju biti celi broj iz intervala 1—31', 0) | ||
end | end | ||
-- Set month abbreviation behaviour, i.e. whether we are outputting | -- Set month abbreviation behaviour, i.e. whether we are outputting | ||
-- " | -- "januar" or "jan". | ||
if args.abbr then | if args.abbr then | ||
self.isAbbreviated = args.abbr == 'on' or yesno(args.abbr) or false | self.isAbbreviated = args.abbr == 'on' or yesno(args.abbr) or false | ||
| Ред 121: | Ред 121: | ||
self.format = args.format | self.format = args.format | ||
else | else | ||
self.format = self.format or ' | self.format = self.format or 'mdy' | ||
end | end | ||
if not Dts.formats[self.format] then | if not Dts.formats[self.format] then | ||
error(string.format( | error(string.format( | ||
"'%s' | "'%s' nije validan format", | ||
tostring(self.format) | tostring(self.format) | ||
), 0) | ), 0) | ||
| Ред 139: | Ред 139: | ||
math.floor(self.addkey) ~= self.addkey | math.floor(self.addkey) ~= self.addkey | ||
then | then | ||
error("'addkey' | error("'addkey' parametar mora biti celi broj iz intervala 0—9999", 0) | ||
end | end | ||
end | end | ||
| Ред 181: | Ред 181: | ||
if not self.year then | if not self.year then | ||
error(string.format( | error(string.format( | ||
"'%s' | "'%s' nije validna vrednost za godinu", | ||
tostring(year) | tostring(year) | ||
), 0) | ), 0) | ||
| Ред 194: | Ред 194: | ||
if not self.month then | if not self.month then | ||
error(string.format( | error(string.format( | ||
"'%s' | "'%s' nije validna vrednost za mesec", | ||
tostring(month) | tostring(month) | ||
), 0) | ), 0) | ||
| Ред 203: | Ред 203: | ||
if not self.day then | if not self.day then | ||
error(string.format( | error(string.format( | ||
"'%s' | "'%s' nije validna vrednost za dan", | ||
tostring(day) | tostring(day) | ||
), 0) | ), 0) | ||
| Ред 210: | Ред 210: | ||
if bc then | if bc then | ||
local bcLower = type(bc) == 'string' and bc:lower() | local bcLower = type(bc) == 'string' and bc:lower() | ||
if bcLower == 'bc' or bcLower == 'bce' or bcLower == ' | if bcLower == 'bc' or bcLower == 'bce' or bcLower == 'p. n. e.' then | ||
if self.year and self.year > 0 then | if self.year and self.year > 0 then | ||
self.year = -self.year | self.year = -self.year | ||
end | end | ||
elseif bcLower ~= 'ad' and bcLower ~= 'ce' and bcLower ~= ' | elseif bcLower ~= 'ad' and bcLower ~= 'ce' and bcLower ~= 'n. e.' then | ||
error(string.format( | error(string.format( | ||
"'%s' | "'%s' nije validna vrednost za kod ere (očekivane vrednosti su 'BC', 'BCE', 'p. n. e.', 'AD', 'CE' ili 'n. e.')", | ||
tostring(bc) | tostring(bc) | ||
), 0) | ), 0) | ||
| Ред 231: | Ред 231: | ||
local function dateError() | local function dateError() | ||
error(string.format( | error(string.format( | ||
"'%s' | "'%s' nije validan datum", | ||
date | date | ||
), 0) | ), 0) | ||
| Ред 271: | Ред 271: | ||
-- wrong. | -- wrong. | ||
error(string.format( | error(string.format( | ||
" | "nepoznata greška se javila pri parsiranju datuma '%s'", | ||
date | date | ||
), 0) | ), 0) | ||
| Ред 397: | Ред 397: | ||
end | end | ||
if self.isAbbreviated then | if self.isAbbreviated then | ||
return self.monthsAbbr[self.month] | return self.monthsAbbr[self.month] | ||
else | else | ||
return self.months[self.month] | return self.months[self.month] | ||
| Ред 421: | Ред 421: | ||
elseif hasDay and hasMonth then | elseif hasDay and hasMonth then | ||
ret[#ret + 1] = self.day | ret[#ret + 1] = self.day | ||
ret[#ret + 1] = ' | ret[#ret + 1] = ' ' | ||
ret[#ret + 1] = self:getMonthName() | ret[#ret + 1] = self:getMonthName() | ||
elseif hasDay then | elseif hasDay then | ||
| Ред 439: | Ред 439: | ||
end | end | ||
ret[#ret + 1] = displayYear | ret[#ret + 1] = displayYear | ||
if self.year < 0 then | if self.year < 0 then | ||
ret[#ret + 1] = ' | ret[#ret + 1] = ' p. n. e.' | ||
end | end | ||
end | end | ||
return table.concat(ret) | return table.concat(ret) | ||
| Ред 505: | Ред 502: | ||
else | else | ||
ret = string.format( | ret = string.format( | ||
'<strong class="error"> | '<strong class="error">Greška u šablonu [[Template:Dts|Dts]]: %s</strong>', | ||
ret | ret | ||
) | ) | ||
Тренутна верзија на датум 5. фебруар 2021. у 13:49
Документацију овог модула можете да направите на страници Модул:Dts/док
local yesno = require('Module:Yesno')
local lang = mw.language.getContentLanguage()
local N_YEAR_DIGITS = 12
local MAX_YEAR = 10^N_YEAR_DIGITS - 1
--------------------------------------------------------------------------------
-- Dts class
--------------------------------------------------------------------------------
local Dts = {}
Dts.__index = Dts
Dts.months = {
"januar",
"februar",
"mart",
"april",
"maj",
"jun",
"jul",
"avgust",
"septembar",
"oktobar",
"novembar",
"decembar"
}
Dts.monthsAbbr = {
"jan",
"feb",
"mar",
"apr",
"maj",
"jun",
"jul",
"avg",
"sep",
"okt",
"nov",
"dec"
}
function Dts._makeMonthSearch(t)
local ret = {}
for i, month in ipairs(t) do
ret[month:lower()] = i
end
return ret
end
Dts.monthSearch = Dts._makeMonthSearch(Dts.months)
Dts.monthSearchAbbr = Dts._makeMonthSearch(Dts.monthsAbbr)
Dts.monthSearchAbbr['sept'] = 9 -- Allow "sept" to match septembar
Dts.formats = {
dmy = true,
mdy = true,
dm = true,
md = true,
my = true,
y = true,
m = true,
d = true,
hide = true
}
function Dts.new(args)
local self = setmetatable({}, Dts)
-- Parse date parameters.
-- In this step we also record whether the date was in DMY or YMD format,
-- and whether the month name was abbreviated.
if args[2] or args[3] or args[4] then
self:parseDateParts(args[1], args[2], args[3], args[4])
elseif args[1] then
self:parseDate(args[1])
end
-- Raise an error on invalid values
if self.year then
if self.year == 0 then
error('godine ne mogu imati vrednost nula', 0)
elseif self.year < -MAX_YEAR then
error(string.format(
'godine ne mogu imati vrednost manju od %s',
lang:formatNum(-MAX_YEAR)
), 0)
elseif self.year > MAX_YEAR then
error(string.format(
'godine ne mogu imati vrednost veću od %s',
lang:formatNum(MAX_YEAR)
), 0)
elseif math.floor(self.year) ~= self.year then
error('godine moraju biti celi broj', 0)
end
end
if self.month and (
self.month < 1
or self.month > 12
or math.floor(self.month) ~= self.month
) then
error('meseci moraju biti celi broj iz intervala 1—12', 0)
end
if self.day and (
self.day < 1
or self.day > 31
or math.floor(self.day) ~= self.day
) then
error('dani moraju biti celi broj iz intervala 1—31', 0)
end
-- Set month abbreviation behaviour, i.e. whether we are outputting
-- "januar" or "jan".
if args.abbr then
self.isAbbreviated = args.abbr == 'on' or yesno(args.abbr) or false
else
self.isAbbreviated = self.isAbbreviated or false
end
-- Set the format string
if args.format then
self.format = args.format
else
self.format = self.format or 'mdy'
end
if not Dts.formats[self.format] then
error(string.format(
"'%s' nije validan format",
tostring(self.format)
), 0)
end
-- Set addkey. This adds a value at the end of the sort key, allowing users
-- to manually distinguish between identical dates.
if args.addkey then
self.addkey = tonumber(args.addkey)
if not self.addkey or
self.addkey < 0 or
self.addkey > 9999 or
math.floor(self.addkey) ~= self.addkey
then
error("'addkey' parametar mora biti celi broj iz intervala 0—9999", 0)
end
end
-- Set whether the displayed date is allowed to wrap or not.
self.isWrapping = args.nowrap == 'off' or yesno(args.nowrap) == false
-- Check for deprecated parameters.
if args.link then
self.hasDeprecatedParameters = true
end
return self
end
function Dts:hasDate()
return (self.year or self.month or self.day) ~= nil
end
-- Find the month number for a month name, and set the isAbbreviated flag as
-- appropriate.
function Dts:parseMonthName(s)
s = s:lower()
local month = Dts.monthSearch[s]
if month then
return month
else
month = Dts.monthSearchAbbr[s]
if month then
self.isAbbreviated = true
return month
end
end
return nil
end
-- Parses separate parameters for year, month, day, and era.
function Dts:parseDateParts(year, month, day, bc)
if year then
self.year = tonumber(year)
if not self.year then
error(string.format(
"'%s' nije validna vrednost za godinu",
tostring(year)
), 0)
end
end
if month then
if tonumber(month) then
self.month = tonumber(month)
elseif type(month) == 'string' then
self.month = self:parseMonthName(month)
end
if not self.month then
error(string.format(
"'%s' nije validna vrednost za mesec",
tostring(month)
), 0)
end
end
if day then
self.day = tonumber(day)
if not self.day then
error(string.format(
"'%s' nije validna vrednost za dan",
tostring(day)
), 0)
end
end
if bc then
local bcLower = type(bc) == 'string' and bc:lower()
if bcLower == 'bc' or bcLower == 'bce' or bcLower == 'p. n. e.' then
if self.year and self.year > 0 then
self.year = -self.year
end
elseif bcLower ~= 'ad' and bcLower ~= 'ce' and bcLower ~= 'n. e.' then
error(string.format(
"'%s' nije validna vrednost za kod ere (očekivane vrednosti su 'BC', 'BCE', 'p. n. e.', 'AD', 'CE' ili 'n. e.')",
tostring(bc)
), 0)
end
end
end
-- This method parses date strings. This is a poor man's alternative to
-- mw.language:formatDate, but it ends up being easier for us to parse the date
-- here than to use mw.language:formatDate and then try to figure out after the
-- fact whether the month was abbreviated and whether we were DMY or MDY.
function Dts:parseDate(date)
-- Generic error message.
local function dateError()
error(string.format(
"'%s' nije validan datum",
date
), 0)
end
local function parseDayOrMonth(s)
if s:find('^%d%d?$') then
return tonumber(s)
end
end
local function parseYear(s)
if s:find('^%d%d%d%d?$') then
return tonumber(s)
end
end
-- Deal with year-only dates first, as they can have hyphens in, and later
-- we need to split the string by all non-word characters, including
-- hyphens. Also, we don't need to restrict years to 3 or 4 digits, as on
-- their own they can't be confused as a day or a month number.
self.year = tonumber(date)
if self.year then
return
end
-- Split the string using non-word characters as boundaries.
date = tostring(date)
local parts = mw.text.split(date, '%W+')
local nParts = #parts
if parts[1] == '' or parts[nParts] == '' or nParts > 3 then
-- We are parsing a maximum of three elements, so raise an error if we
-- have more. If the first or last elements were blank, then the start
-- or end of the string was a non-word character, which we will also
-- treat as an error.
dateError()
elseif nParts < 1 then
-- If we have less than one element, then something has gone horribly
-- wrong.
error(string.format(
"nepoznata greška se javila pri parsiranju datuma '%s'",
date
), 0)
end
if nParts == 1 then
-- This can be either a month name or a year.
self.month = self:parseMonthName(parts[1])
if not self.month then
self.year = parseYear(parts[1])
if not self.year then
dateError()
end
end
elseif nParts == 2 then
-- This can be any of the following formats:
-- DD Month
-- Month DD
-- Month YYYY
-- YYYY-MM
self.month = self:parseMonthName(parts[1])
if self.month then
-- This is either Month DD or Month YYYY.
self.year = parseYear(parts[2])
if not self.year then
-- This is Month DD.
self.format = 'mdy'
self.day = parseDayOrMonth(parts[2])
if not self.day then
dateError()
end
end
else
self.month = self:parseMonthName(parts[2])
if self.month then
-- This is DD Month.
self.format = 'dmy'
self.day = parseDayOrMonth(parts[1])
if not self.day then
dateError()
end
else
-- This is YYYY-MM.
self.year = parseYear(parts[1])
self.month = parseDayOrMonth(parts[2])
if not self.year or not self.month then
dateError()
end
end
end
elseif nParts == 3 then
-- This can be any of the following formats:
-- DD Month YYYY
-- Month DD, YYYY
-- YYYY-MM-DD
-- DD-MM-YYYY
self.month = self:parseMonthName(parts[1])
if self.month then
-- This is Month DD, YYYY.
self.format = 'mdy'
self.day = parseDayOrMonth(parts[2])
self.year = parseYear(parts[3])
if not self.day or not self.year then
dateError()
end
else
self.day = parseDayOrMonth(parts[1])
if self.day then
self.month = self:parseMonthName(parts[2])
if self.month then
-- This is DD Month YYYY.
self.format = 'dmy'
self.year = parseYear(parts[3])
if not self.year then
dateError()
end
else
-- This is DD-MM-YYYY.
self.format = 'dmy'
self.month = parseDayOrMonth(parts[2])
self.year = parseYear(parts[3])
if not self.month or not self.year then
dateError()
end
end
else
-- This is YYYY-MM-DD
self.year = parseYear(parts[1])
self.month = parseDayOrMonth(parts[2])
self.day = parseDayOrMonth(parts[3])
if not self.year or not self.month or not self.day then
dateError()
end
end
end
end
end
function Dts:makeSortKey()
local year, month, day
local nYearDigits = N_YEAR_DIGITS
if self:hasDate() then
year = self.year or os.date("*t").year
if year < 0 then
year = -MAX_YEAR - 1 - year
nYearDigits = nYearDigits + 1 -- For the minus sign
end
month = self.month or 1
day = self.day or 1
else
-- Blank {{dts}} transclusions should sort last.
year = MAX_YEAR
month = 99
day = 99
end
return string.format(
'%0' .. nYearDigits .. 'd-%02d-%02d-%04d',
year, month, day, self.addkey or 0
)
end
function Dts:getMonthName()
if not self.month then
return ''
end
if self.isAbbreviated then
return self.monthsAbbr[self.month]
else
return self.months[self.month]
end
end
function Dts:makeDisplay()
if self.format == 'hide' then
return ''
end
local hasYear = self.year and self.format:find('y')
local hasMonth = self.month and self.format:find('m')
local hasDay = self.day and self.format:find('d')
local isMonthFirst = self.format:find('md')
local ret = {}
if hasDay and hasMonth and isMonthFirst then
ret[#ret + 1] = self:getMonthName()
ret[#ret + 1] = ' '
ret[#ret + 1] = self.day
if hasYear then
ret[#ret + 1] = ','
end
elseif hasDay and hasMonth then
ret[#ret + 1] = self.day
ret[#ret + 1] = ' '
ret[#ret + 1] = self:getMonthName()
elseif hasDay then
ret[#ret + 1] = self.day
elseif hasMonth then
ret[#ret + 1] = self:getMonthName()
end
if hasYear then
if hasDay or hasMonth then
ret[#ret + 1] = ' '
end
local displayYear = math.abs(self.year)
if displayYear > 9999 then
displayYear = lang:formatNum(displayYear)
else
displayYear = tostring(displayYear)
end
ret[#ret + 1] = displayYear
if self.year < 0 then
ret[#ret + 1] = ' p. n. e.'
end
end
return table.concat(ret)
end
function Dts:renderTrackingCategories()
if self.hasDeprecatedParameters then
return '[[Category:Dts templates with deprecated parameters]]'
else
return ''
end
end
function Dts:__tostring()
local root = mw.html.create()
-- Sort key
root:tag('span')
:addClass('sortkey')
:css('display', 'none')
:css('speak', 'none')
:wikitext(self:makeSortKey())
-- Display
if self:hasDate() then
if self.isWrapping then
root:wikitext(self:makeDisplay())
else
root:tag('span')
:css('white-space', 'nowrap')
:wikitext(self:makeDisplay())
end
end
-- Tracking categories
root:wikitext(self:renderTrackingCategories())
return tostring(root)
end
--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------
local p = {}
function p._exportClasses()
return {
Dts = Dts
}
end
function p._main(args)
local success, ret = pcall(function ()
local dts = Dts.new(args)
return tostring(dts)
end)
if success then
return ret
else
ret = string.format(
'<strong class="error">Greška u šablonu [[Template:Dts|Dts]]: %s</strong>',
ret
)
if mw.title.getCurrentTitle().namespace == 0 then
-- Only categorise in the main namespace
ret = ret .. '[[Category:Dts templates with errors]]'
end
return ret
end
end
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = 'Template:Dts',
})
return p._main(args)
end
return p