Модуль:Calendar: различия между версиями
Buto (обсуждение | вклад) Новая страница: «local p = {} -- Необходимые модули и переменные local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno') local mwlang = mw.getContentLanguage() local err = "―" -- NthDay nil result local tCon = table.concat -- 00) Блок многократно используемых списков local bool_to_number={ [true]=1, [false]=0 } local monthlang = {"января","февраля","марта","а...» |
Buto (обсуждение | вклад) Нет описания правки |
||
| (не показана 1 промежуточная версия этого же участника) | |||
| Строка 7: | Строка 7: | ||
local tCon = table.concat | local tCon = table.concat | ||
-- | -- Блок многократно используемых списков | ||
local bool_to_number={ [true]=1, [false]=0 } | local bool_to_number={ [true]=1, [false]=0 } | ||
local monthlang = {"января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"} | local monthlang = {"января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"} | ||
| Строка 46: | Строка 46: | ||
-- US Millitary (for RFC-822) | -- US Millitary (for RFC-822) | ||
Z='+00:00', A='-01:00', M='-12:00', N='+01:00', Y='+12:00', | Z='+00:00', A='-01:00', M='-12:00', N='+01:00', Y='+12:00', | ||
-- российское обозначение | |||
["МСК"]='+03:00', | |||
} | } | ||
-- имена по конвенции [[:Категория:Тептар:Статьи по типам недостатков]]: | |||
-- «ошибочная работа» — результат выдать не удалось; «неполные или некорректные | |||
-- параметры» — результат выдан, но параметры пришлось восстанавливать эвристиками | |||
local cat_erroneous = "[[Категория:Тептар:Статьи с ошибочной работой Модуль:Calendar]]" | |||
local cat_incomplete = "[[Категория:Тептар:Статьи с неполными или некорректными параметрами Модуль:Calendar]]" | |||
local category = { | local category = { | ||
["no_parameters"]= | ["no_parameters"] = cat_erroneous, | ||
["incomplete_parameters"] = cat_incomplete, | |||
["incomplete_parameters"]= | ["without_verification"] = cat_incomplete, | ||
["erroneous_parameters"] = cat_erroneous, | |||
["without_verification"]= | |||
["erroneous_parameters"]= | |||
} | } | ||
| Строка 76: | Строка 79: | ||
-- [""]="", | -- [""]="", | ||
} | } | ||
local pattern = { -- для распознавания дат, переданных одним строчным параметром | local pattern = { -- для распознавания дат, переданных одним строчным параметром | ||
| Строка 140: | Строка 131: | ||
end | end | ||
-- | -- Блок общих функций | ||
local function trim(str) | local function trim(str) | ||
if not str then return nil | if not str then return nil | ||
| Строка 207: | Строка 198: | ||
end | end | ||
-- | -- Блок общих проверочных функций, связанных с датами | ||
local function unwarp(tbl) | local function unwarp(tbl) | ||
if not tbl then return "" | if not tbl then return "" | ||
| Строка 306: | Строка 297: | ||
end | end | ||
-- | -- Блок функций для обработки ввода-вывода дат | ||
local function undate(tbl) | local function undate(tbl) | ||
| Строка 352: | Строка 343: | ||
return date --, error_data | return date --, error_data | ||
end | end | ||
-- | -- DEPRECATED | ||
local numstr2date = function(numstr) | local numstr2date = function(numstr) | ||
local format = "Y-m-d" | local format = "Y-m-d" | ||
| Строка 398: | Строка 389: | ||
end | end | ||
local function day2lang(datein,wikidate,wiki,inner_brt) | -- prefix — текст перед днём внутри подписи ссылки (открывающая скобка при inner_brt) | ||
local function day2lang(datein,wikidate,wiki,inner_brt,prefix) | |||
-- if not isdate(wikidate) then wiki = false end | -- if not isdate(wikidate) then wiki = false end | ||
if not ispartdate(datein) then return "" end | if not ispartdate(datein) then return "" end | ||
| Строка 405: | Строка 397: | ||
if (not datein.month) then datein.month = "" end | if (not datein.month) then datein.month = "" end | ||
if (not datein.day) then datein.day = "" end | if (not datein.day) then datein.day = "" end | ||
if not prefix then prefix = "" end | |||
local monlan = monthlang[datein.month] or "" | local monlan = monthlang[datein.month] or "" | ||
if wiki and not inner_brt then | if wiki and not inner_brt then | ||
output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "", | output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "", | ||
"|", (datein.day or ""), dm_separ, monlan, "]]"}) | "|", prefix, (datein.day or ""), dm_separ, monlan, "]]"}) | ||
elseif wiki then | elseif wiki then | ||
output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "", | output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "", | ||
"|", (datein.day or ""), dm_separ, monlan}) | "|", prefix, (datein.day or ""), dm_separ, monlan}) | ||
else | else | ||
output = tCon({datein.day, dm_separ, monlan}) | output = tCon({prefix, datein.day, dm_separ, monlan}) | ||
end | end | ||
return trim(output) | return trim(output) | ||
| Строка 482: | Строка 475: | ||
gd.month, jd.month = nil, nil | gd.month, jd.month = nil, nil | ||
end | end | ||
if (not not cd.month) and wm then | if (not not cd.month) and wm then | ||
return tCon({comment[1] .. trim(day2lang(jd,jdate,false) .. " " .. year2lang(jd.year,yearmark,false)) .. comment[2], | -- ссылка тут сквозная (закрывается после общего месяца), поэтому открывающая | ||
trim( | -- скобка уходит внутрь подписи: [[21 февраля|(21) февраля]], а не ([[21 февраля|21) февраля]] | ||
local gday = day2lang(gd,gdate,wd,wm,left) | |||
if gday == "" then gday = left end | |||
return tCon({comment[1] .. trim(day2lang(jd,jdate,false) .. " " .. year2lang(jd.year,yearmark,false)) .. comment[2], | |||
trim(gday .. " " .. year2lang(gd.year,yearmark,wy)) .. right, | |||
day2lang(cd,gdate,false) .. "]]", trim(year2lang(cd.year,yearmark,wy)..msg)}, " ") | day2lang(cd,gdate,false) .. "]]", trim(year2lang(cd.year,yearmark,wy)..msg)}, " ") | ||
end | end | ||
return tCon({comment[1] .. trim(day2lang(jd,jdate,false) .. " " .. year2lang(jd.year,yearmark,false)) .. comment[2], | return tCon({comment[1] .. trim(day2lang(jd,jdate,false) .. " " .. year2lang(jd.year,yearmark,false)) .. comment[2], | ||
trim(left .. day2lang(gd,gdate,wd) .. " " .. year2lang(gd.year,yearmark,wy)) .. right, | trim(left .. day2lang(gd,gdate,wd) .. " " .. year2lang(gd.year,yearmark,wy)) .. right, | ||
| Строка 492: | Строка 489: | ||
end | end | ||
-- | -- Блок функций для перевода дат с использованием [[Юлианская дата]] | ||
local function gri2jd( datein ) | local function gri2jd( datein ) | ||
| Строка 583: | Строка 580: | ||
end | end | ||
-- | -- Функции для обработки UTC | ||
local function utc(str,margin) | local function utc(str,margin) | ||
| Строка 604: | Строка 601: | ||
error("Нет входящей строки") | error("Нет входящей строки") | ||
elseif str:byte(1) == 43 then | elseif str:byte(1) == 43 then | ||
elseif inbord(str:byte(1),48,57) then cat = "[[Категория: | elseif inbord(str:byte(1),48,57) then cat = "[[Категория:Тептар:Ошибка в часовом поясе НП]]" | ||
elseif str:byte(1) == 45 or string.sub(str,1,3) == "−" or string.sub(str,1,1)=="-" then d = -1 | elseif str:byte(1) == 45 or string.sub(str,1,3) == "−" or string.sub(str,1,1)=="-" then d = -1 | ||
else | else | ||
| Строка 629: | Строка 626: | ||
local h, m = math.modf(math.abs(timedec)) | local h, m = math.modf(math.abs(timedec)) | ||
hmarg = h | hmarg = h | ||
mmarg = math.floor(m*60) | mmarg = math.floor(m*60 + 0.5) -- без +0.5 «+4:35» давало 4:34: m*60 = 34.999… | ||
end | end | ||
if timedec == 0 then | if timedec == 0 then | ||
| Строка 642: | Строка 639: | ||
end | end | ||
-- | -- Блок функций ввода-вывода | ||
function p.NthDay( frame ) | function p.NthDay( frame ) | ||
| Строка 650: | Строка 647: | ||
if not format then format = "%d.%m.%y" end | if not format then format = "%d.%m.%y" end | ||
if not inbord(num,-5,5) then | if not inbord(num,-5,5) then | ||
return | return e.start .. "The number must be between -5 and 5" .. e.ending .. category.erroneous_parameters | ||
elseif num == 0 then | elseif num == 0 then | ||
return | return e.start .. "The number must not be zero" .. e.ending .. category.erroneous_parameters end | ||
if not inbord(wday,0,6) then | if not inbord(wday,0,6) then | ||
return | return e.start .. "The day of the week must be between 0 and 6" .. e.ending .. category.erroneous_parameters end | ||
if not inbord(mont,1,12) then | if not inbord(mont,1,12) then | ||
return | return e.start .. "The month must be between 1 and 12" .. e.ending .. category.erroneous_parameters end | ||
if not inbord(yea,0,9999) then | if not inbord(yea,0,9999) then | ||
return | return e.start .. "Wrong year number" .. e.ending .. category.erroneous_parameters end | ||
if inbord(num,1,5) then | if inbord(num,1,5) then | ||
local m_start = os.time{year=yea, month=mont, day=1, hour=0} | local m_start = os.time{year=yea, month=mont, day=1, hour=0} | ||
| Строка 724: | Строка 721: | ||
local txtDateOut, date, status = p.bxDate(txtDateIn, strFormat, params) | local txtDateOut, date, status = p.bxDate(txtDateIn, strFormat, params) | ||
if status.brk then | if status.brk then | ||
return | return e.start .. status.errorText .. e.ending .. (status.errorCat or "") | ||
else | else | ||
return txtDateOut | return txtDateOut | ||
| Строка 730: | Строка 727: | ||
end | end | ||
function p.bxDate( txtDateIn , strFormat, params ) | function p.bxDate( txtDateIn , strFormat, params ) | ||
local txtDateOut, date, status = "", {}, {brk = false, errorCat = "", errorText = ""} | local txtDateOut, date, status = "", {}, {brk = false, errorCat = "", errorText = ""} | ||
strFormat = strFormat or "j xg Y" | strFormat = strFormat or "j xg Y" | ||
| Строка 772: | Строка 769: | ||
end | end | ||
function p.ToDate( frame ) | function p.ToDate( frame ) | ||
local args = getArgs(frame, { frameOnly = true }) | local args = getArgs(frame, { frameOnly = true }) | ||
local mwlang = mw.getContentLanguage() | local mwlang = mw.getContentLanguage() | ||
| Строка 785: | Строка 782: | ||
-- =p.unitime(mw.getCurrentFrame():newChild{title="smth",args={"−1:30","1"}}) | -- =p.unitime(mw.getCurrentFrame():newChild{title="smth",args={"−1:30","1"}}) | ||
-- ── Разбор пользовательской записи часового пояса ──────────────────────────── | |||
-- Признак того, что в строке зашито второе значение (зимнее/летнее) или | |||
-- диапазон: такую строку разбирать нельзя — потеряется половина смысла. | |||
local function has_second_value(tail) | |||
if tail == '' then return false end | |||
local t = mw.ustring.lower(tail) | |||
return mw.ustring.find(t, '[+±−%-]%s*%d') ~= nil | |||
or mw.ustring.find(t, 'лет[а-яё]') ~= nil | |||
or mw.ustring.find(t, 'зим[а-яё]') ~= nil | |||
or mw.ustring.find(t, 'dst') ~= nil | |||
or mw.ustring.find(t, 'summer') ~= nil | |||
or mw.ustring.find(t, 'winter') ~= nil | |||
end | |||
-- Минуты из записи «часы<разделитель>дробь». | |||
-- «:30» — канон; «.30» и «,30» — те же 30 минут; «.5» и «,5» — половина часа. | |||
-- Второе возвращаемое значение — признак того, что применена эвристика. | |||
local function minutes_from(sep, frac) | |||
if frac == '' then return 0, false end | |||
local n = tonumber(frac) | |||
if sep == ':' then return n, false end | |||
if mw.ustring.len(frac) == 2 and n <= 59 then return n, true end | |||
return math.floor(tonumber('0.' .. frac) * 60 + 0.5), true | |||
end | |||
-- Приводит вход к каноническому «±H:MM» для utc(), отдельно возвращая | |||
-- неразобранный хвост строки и признак применённой эвристики. | |||
-- Первое значение nil — разбор не удался. | |||
local function split_tz(input) | |||
local abbr = known_tzs[mw.ustring.upper(input)] | |||
if abbr then return abbr, '', false end | |||
local letters, sign, hh, sep, mm, tail = mw.ustring.match( | |||
input, '^(%a*)%s*([+±−%-]?)%s*(%d+)([:%.,]?)(%d*)(.-)%s*$') | |||
if not hh then return nil end | |||
if letters ~= '' and mw.ustring.upper(letters) ~= 'UTC' then return nil end | |||
if sep ~= '' and mm == '' then return nil end -- «+3:» — обрубок | |||
if has_second_value(tail) then return nil end | |||
local minutes, guessed = minutes_from(sep, mm) | |||
if minutes > 59 then return nil end | |||
if sign == '' or sign == '±' then sign = '+' end | |||
return sign .. hh .. ':' .. string.format('%02d', minutes), tail, | |||
guessed or tail ~= '' | |||
end | |||
function p.unitime( frame ) | function p.unitime( frame ) | ||
local args = getArgs(frame, { frameOnly = true }) | local args = getArgs(frame, { frameOnly = true }) | ||
local DST = 0 | local DST = 0 | ||
if | if args[2] then DST = 1 end | ||
local input = trim(args[1] or "") | |||
if input == "" then return "" end | |||
local input = args[1] | -- уже оформленное (Тептар-ссылка или шаблон) возвращается как есть | ||
if | if string.sub(input,1,1) == '[' or string.sub(input,1,1) == '{' then | ||
return input | |||
end | |||
local utcin, tail, heuristic = split_tz(input) | |||
if not utcin then | |||
-- не распознано: вернуть как есть, пометить категорией | |||
return input .. category.erroneous_parameters | |||
-- | |||
end | end | ||
local ok, output | |||
if DST == 0 then | |||
local output | ok, output = pcall(function() return utc(utcin) .. tail end) | ||
if DST == 0 then output = utc(utcin) | else | ||
else output = utc(utcin) .. ", [[летнее время|летом]] " .. utc(utcin,DST) | ok, output = pcall(function() | ||
return utc(utcin) .. tail .. ", [[летнее время|летом]] " .. utc(utcin,DST) | |||
end) | |||
end | end | ||
if not ok then return input .. category.erroneous_parameters end | |||
if heuristic then return output .. category.incomplete_parameters end | |||
return output | return output | ||
end | end | ||
-- | -- DEPRECATED | ||
-- =p.OldDate(mw.getCurrentFrame():newChild{title="smth",args={"20.02.2020","ю",["bc"]="1",["wd"]="1",["wy"]="1",["sq_brts"]="1",["yearmark"]="г."}}) | -- =p.OldDate(mw.getCurrentFrame():newChild{title="smth",args={"20.02.2020","ю",["bc"]="1",["wd"]="1",["wy"]="1",["sq_brts"]="1",["yearmark"]="г."}}) | ||
function p.OldDate( frame ) | function p.OldDate( frame ) | ||
| Строка 826: | Строка 864: | ||
local gdate, jdate = {}, {} | local gdate, jdate = {}, {} | ||
local strin = args[1] | local strin = args[1] | ||
local cal = args[2]:lower() | local cal = (args[2] or "г"):lower() | ||
local bc = is(args["bc"]) | local bc = is(args["bc"]) | ||
local wd = is(args["wd"]) | local wd = is(args["wd"]) | ||
| Строка 999: | Строка 1037: | ||
return err .. category.incomplete_parameters | return err .. category.incomplete_parameters | ||
end | end | ||
end | |||
-- Блок реестра календарей и вывода дат по разным календарям | |||
-- "ГГГГ-ММ-ДД" → таблица {year, month, day} | |||
local function iso2date(iso) | |||
local y, m, d = string.match(iso or "", "^(-?%d+)-(%d%d?)-(%d%d?)$") | |||
return {["year"]=purif(y), ["month"]=purif(m), ["day"]=purif(d)} | |||
end | |||
-- Коптский календарь: арифметика через JD. Эпоха 1.1.1 = JD 1825030 | |||
-- (29 августа 284 года по юлианскому). Високосный год: y mod 4 == 3. | |||
local function coptic2jd(y, m, d) | |||
return 1825029 + 365*(y-1) + math.floor(y/4) + 30*(m-1) + d | |||
end | |||
local function jd2coptic(jd) | |||
local year = math.floor((4*(jd - 1825030) + 1463)/1461) | |||
local month = math.floor((jd - coptic2jd(year, 1, 1))/30) + 1 | |||
local day = jd - coptic2jd(year, month, 1) + 1 | |||
return {["year"]=year, ["month"]=month, ["day"]=day} | |||
end | |||
-- Реестр календарей. Два вида записей: | |||
-- fmt = календарь умеет сам движок MediaWiki (коды x* в formatDate); | |||
-- conv = своя математика: функция JD → таблица {year, month, day}. | |||
-- Новый календарь = одна строка (fmt) либо строка + пара функций x2jd/jd2x. | |||
local calreg = { | |||
{["id"]="григорианский", ["name"]="[[Григорианский календарь|Григорианский]]", ["fmt"]="j xg Y"}, | |||
{["id"]="юлианский", ["name"]="[[Юлианский календарь|Юлианский]]", ["conv"]=jd2jul}, | |||
{["id"]="исламский", ["name"]="[[Исламский календарь|Исламский (хиджра)]]", ["fmt"]="xmj xmF xmY"}, | |||
{["id"]="иранский", ["name"]="[[Иранский календарь|Иранский (солнечная хиджра)]]", ["fmt"]="xij xiF xiY"}, | |||
{["id"]="еврейский", ["name"]="[[Еврейский календарь|Еврейский]]", ["fmt"]="xjj xjF xjY"}, | |||
{["id"]="тайский", ["name"]="[[Тайский солнечный календарь|Тайский солнечный]]", ["fmt"]="j xg xkY"}, | |||
{["id"]="миньго", ["name"]="[[Миньго|Миньго]]", ["fmt"]="j xg xoY"}, | |||
{["id"]="нэнго", ["name"]="[[Японское летосчисление|Японский (нэнго)]]", ["fmt"]="j xg (xtY)"}, | |||
{["id"]="коптский", ["name"]="[[Коптский календарь|Коптский]]", ["conv"]=jd2coptic}, | |||
} | |||
local function cal_render(entry, iso, jd) | |||
if entry.fmt then | |||
return mwlang:formatDate(entry.fmt, iso) | |||
end | |||
local d = entry.conv(jd) | |||
return tCon({d.day, ".", string.format("%02d", d.month), ".", d.year}) | |||
end | |||
-- {{#invoke:Песочница/Carn/Calendar|CalDate|2026-07-27|еврейский}} → 13 Ав 5786 | |||
-- Первый аргумент пустой = сегодня (по UTC). | |||
function p.CalDate(frame) | |||
local args = getArgs(frame, { frameOnly = true }) | |||
local iso = trim(args[1] or "") | |||
if iso == "" then iso = mwlang:formatDate("Y-m-d") end | |||
local date = iso2date(iso) | |||
if not isdate(date) then | |||
return e.start .. string.format(e.box_date, iso) .. e.ending .. category.erroneous_parameters | |||
end | |||
local id = trim(args[2] or "") | |||
for i = 1, #calreg do | |||
if calreg[i].id == id then | |||
return cal_render(calreg[i], iso, gri2jd(date)) | |||
end | |||
end | |||
return e.start .. string.format(e.unknown_param, id) .. e.ending .. category.erroneous_parameters | |||
end | |||
-- Дашборд: {{#invoke:Песочница/Carn/Calendar|Today}} → таблица «сегодня по всем | |||
-- календарям реестра». Необязательный аргумент — фиксированная дата для тестов. | |||
function p.Today(frame) | |||
local args = getArgs(frame, { frameOnly = true }) | |||
local iso = trim(args[1] or "") | |||
if iso == "" then iso = mwlang:formatDate("Y-m-d") end | |||
local date = iso2date(iso) | |||
if not isdate(date) then | |||
return e.start .. string.format(e.box_date, iso) .. e.ending .. category.erroneous_parameters | |||
end | |||
local jd = gri2jd(date) | |||
local rows = {'{| class="wikitable sortable"', '! Календарь !! Дата'} | |||
for i = 1, #calreg do | |||
table.insert(rows, '|-') | |||
table.insert(rows, '| ' .. calreg[i].name .. ' || ' .. cal_render(calreg[i], iso, jd)) | |||
end | |||
table.insert(rows, '|}') | |||
return tCon(rows, "\n") | |||
end | |||
-- Блок семейства {{OldStyleDate}} ({{СС}}, {{СС2}}, {{СС3}}, {{СС4}}) — T276471. | |||
local cat_mismatch = "[[Категория:Тептар:Статьи с несовпадающими датами старого и нового стиля]]" | |||
local jul_title = "по юлианскому календарю" | |||
local gri_title = "по григорианскому календарю" | |||
local function ifset(v) return v ~= nil and trim(v) ~= "" end | |||
-- {{Comment|text|title}} без вызова шаблона: те же стили и тот же span | |||
local function comment_span(frame, text, title) | |||
local styles = frame:extensionTag("templatestyles", "", { src = "Шаблон:Comment/styles.css" }) | |||
title = title:gsub('"', """):gsub("<", "<"):gsub(">", ">") | |||
return tCon({styles, '<span class="ts-comment-commentedText" title="', title, '">', text, "</span>"}) | |||
end | |||
-- {{До символа|s| }} — текст до первого пробела | |||
local function before_space(s) return (s:match("^([^ ]*)")) end | |||
-- юлианская дата → JD без проверки (переполнение нормализуется, как в PHP strtotime) | |||
local function jul2jd_lenient(y, m, d) | |||
local a = math.floor((14 - m)/12) | |||
local yy = y + 4800 - a | |||
local mm = m + 12*a - 3 | |||
return d + math.floor((153*mm + 2)/5) + 365*yy + math.floor(yy/4) - 32083 | |||
end | |||
-- Проверка пары дат {{СС}}: старый стиль (od, om, oy) должен давать новый (nd, nm, ny). | |||
-- Возвращает категорию или "". Год неизвестен → перебор эпох с разрывом 10…13 дней, | |||
-- по високосному и невисокосному году на каждую (февраль). | |||
local function osd_check(d1, m1, y1, d2, m2, y2) | |||
local nd = tonumber(d1:match("^%s*(%d+)%s*$")) | |||
local nm = month_to_num[trim(m1)] | |||
local ny = tonumber((y1:match("%d+"))) | |||
local od = tonumber(d2:match("^%s*(%d+)%s*$")) | |||
local om, oy = nm, ny | |||
if ifset(m2) then om = month_to_num[trim(m2)] | |||
elseif not od then -- «24 августа» одним параметром | |||
od = tonumber(d2:match("^%s*(%d+)")) | |||
om = month_to_num[mw.ustring.match(d2, "(%a+)") or ""] | |||
end | |||
if ifset(y2) then oy = tonumber((y2:match("%d+"))) end | |||
if not (nd and nm and od and om) then return "" end -- диапазон, прочерк — не проверяем | |||
if not isdate({year = oy or 1900, month = om, day = od}, true) then return category.incomplete_parameters end | |||
local years = oy and {oy} or {1600, 1650, 1704, 1750, 1804, 1850, 1904, 1950} | |||
for _, y in ipairs(years) do | |||
local g = jd2gri(jul2jd_lenient(y, om, od)) | |||
if g.day == nd and g.month == nm then | |||
if not oy or not ny or g.year == ny then return "" end | |||
if not ifset(y2) then return category.incomplete_parameters end -- год НС другой, а {{{6}}} не задан | |||
end | |||
end | |||
return cat_mismatch | |||
end | |||
-- {{OldStyleDate|день НС|месяц НС|год НС|день СС|месяц СС|год СС|[}} ; 7-й параметр = квадратные скобки | |||
function p.OldStyleDate(frame) | |||
local a = frame.args | |||
local d1, m1, y1, d2, m2, y2 = a[1] or "", a[2] or "", a[3] or "", a[4] or "", a[5] or "", a[6] or "" | |||
local lb, rb = "(", ")" | |||
if ifset(a[7]) then lb, rb = "[", "]" end | |||
local function jul(text) return comment_span(frame, text, jul_title) end | |||
local year_link = "" | |||
if ifset(y1) then year_link = tCon({" [[", before_space(y1), " год|", y1, "]]"}) end | |||
local m1_tail = ifset(m1) and (" " .. m1) or "" | |||
local out | |||
if ifset(y2) then | |||
out = tCon({jul(d2 .. " " .. m2 .. " " .. y2), " ", lb, "[[", d1, " ", m1, "]] [[", before_space(y1), " год|", y1, "]]", rb}) | |||
elseif ifset(m2) then | |||
out = tCon({jul(d2 .. " " .. m2), " ", lb, "[[", d1, m1_tail, "]]", rb, year_link}) | |||
else | |||
out = tCon({jul(d2), " [[", d1, " ", m1, "|", lb, d1, rb, m1_tail, "]]", year_link}) | |||
end | |||
return out .. osd_check(d1, m1, y1, d2, m2, y2) | |||
end | |||
-- {{OldStyleDate3|д.м.гггг|года|bracket=|bracket end=}} — дата по старому стилю, новый стиль считается | |||
function p.OldStyleDate3(frame) | |||
local a = frame.args | |||
local strin, ym = a[1] or "", trim(a[2] or "") | |||
local lb = ifset(a["bracket"]) and trim(a["bracket"]) or "(" | |||
local rb = ifset(a["bracket end"]) and trim(a["bracket end"]) or ")" | |||
local d, m, y = strin:match("^%s*(%d%d?)%s*[%.%-/]%s*(%d%d?)%s*[%.%-/%s]%s*(%d%d%d%d?)%s*$") | |||
if not d then -- запасной разбор движком, как #time | |||
local ok, iso = pcall(function() return mwlang:formatDate("Y-m-d", strin) end) | |||
if ok then y, m, d = iso:match("^(%d+)-(%d+)-(%d+)$") end | |||
end | |||
if not d then | |||
return e.start .. string.format(e.no_valid_date, strin) .. e.ending .. category.erroneous_parameters | |||
end | |||
d, m, y = tonumber(d), tonumber(m), tonumber(y) | |||
local msg = "" | |||
if not (m >= 1 and m <= 12 and isdate({year = y, month = m, day = d}, true)) then | |||
msg = category.incomplete_parameters -- 30.02 и т. п.: нормализуем, как PHP, и помечаем | |||
end | |||
local jd = jul2jd_lenient(y, m, d) | |||
local jdate, gdate = jd2jul(jd), jd2gri(jd) | |||
local jD, jM, jY = tostring(jdate.day), monthlang[jdate.month], tostring(jdate.year) | |||
local gD, gM, gY = tostring(gdate.day), monthlang[gdate.month], tostring(gdate.year) | |||
local ymk = (ym ~= "") and (" " .. ym) or "" | |||
local function jul(text) return comment_span(frame, text, jul_title) end | |||
if jdate.year*10000 + jdate.month*100 + jdate.day <= 15821004 then -- до введения григорианского | |||
return jul(jD .. " " .. jM .. " " .. jY .. ymk) .. msg | |||
end | |||
if jdate.month == gdate.month then | |||
return tCon({comment_span(frame, jD, jD .. " " .. jM .. " " .. jul_title), " ", lb, | |||
"[[", gD, " ", gM, '|<span title="', gD, " ", gM, " ", gri_title, '">', gD, "</span>]]", rb, | |||
" ", gM, " [[", gY, " год|", gY, ymk, "]]", msg}) | |||
elseif jdate.year == gdate.year then | |||
return tCon({jul(jD .. " " .. jM), " ", lb, | |||
"[[", gD, " ", gM, '|<span title="', gri_title, '">', gD, " ", gM, "</span>]]", rb, | |||
" [[", gY, " год|", gY, ymk, "]]", msg}) | |||
end | |||
return tCon({jul(jD .. " " .. jM .. " " .. jY .. ymk), " ", lb, | |||
"[[", gD, " ", gM, '|<span title="', gri_title, '">', gD, " ", gM, "</span>]]", | |||
" [[", gY, " год|<span title=\"", gri_title, '">', gY, "</span>]]", rb, msg}) | |||
end | end | ||
return p | return p | ||