Модуль:Calendar: различия между версиями
Материал из FetbukWiki
https://ru.wikipedia.org/wiki/>Carn (…) |
м (141 версия импортирована) |
||
(не показаны 23 промежуточные версии 4 участников) | |||
Строка 3: | Строка 3: | ||
local getArgs = require('Module:Arguments').getArgs | local getArgs = require('Module:Arguments').getArgs | ||
local yesno = require('Module:Yesno') | local yesno = require('Module:Yesno') | ||
local | local mwlang = mw.getContentLanguage() | ||
local err = "―" -- NthDay nil result | local err = "―" -- NthDay nil result | ||
local tCon = table.concat | |||
-- 00) Блок многократно используемых списков | -- 00) Блок многократно используемых списков | ||
Строка 14: | Строка 15: | ||
local params = { {"г", "g"}, {"ю", "j"}} | local params = { {"г", "g"}, {"ю", "j"}} | ||
local comment = { '<span style="border-bottom: 1px dotted; cursor: help" title="по юлианскому календарю">','</span>'} | local comment = { '<span style="border-bottom: 1px dotted; cursor: help" title="по юлианскому календарю">','</span>'} | ||
-- duplicates: | |||
-- AST, BST, CST, ECT, IST, MST, PST, SST, | |||
local known_tzs = { | local known_tzs = { | ||
ACDT='+10:30', ACST='+09:30', ACT ='+08:00', ADT ='-03:00', AEDT ='+11:00', | ACDT='+10:30', ACST='+09:30', ACT ='+08:00', ADT ='-03:00', AEDT ='+11:00', | ||
Строка 41: | Строка 43: | ||
SST ='+08:00', TAHT='-10:00', THA ='+07:00', UTC ='+00:00', UYST ='-02:00', | SST ='+08:00', TAHT='-10:00', THA ='+07:00', UTC ='+00:00', UYST ='-02:00', | ||
UYT ='-03:00', VET ='-04:30', VLAT='+10:00', WAT ='+01:00', WEDT ='+01:00', | UYT ='-03:00', VET ='-04:30', VLAT='+10:00', WAT ='+01:00', WEDT ='+01:00', | ||
WEST='+01:00', WET ='+00:00', YAKT='+09:00', YEKT ='+05 | WEST='+01:00', WET ='+00:00', YAKT='+09:00', YEKT ='+05:00', | ||
-- 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', | ||
} | } | ||
local category = { | |||
["no_parameters"]= | |||
"<!--[[Категория:Модуль:Calendar:Страницы без параметров]]-->", | |||
["incomplete_parameters"]= | |||
"<!--[[Категория:Модуль:Calendar:Страницы с неполными или некорректными параметрами]]-->", | |||
["without_verification"]= | |||
"<!--[[Категория:Модуль:Calendar:Страницы без проверки параметров]]-->", | |||
["erroneous_parameters"]= | |||
"<!--[[Категория:Модуль:Calendar:Страницы с ошибочными параметрами]]-->" | |||
} | |||
-- несколько параметров передаются вместе с кодом ошибки в таблице, один может быть передан простым значением | |||
local e = { | |||
["start"]="<span class=error>Ошибка: ", | |||
["ending"]=".</span>", | |||
["no_pattern_match"]="строка «%s» не совпадает с заданными паттернами", | |||
["no_valid_date"]="дата «%s» не является корректной", | |||
["wrong_jd"]="юлианская дата %s вне диапазона", | |||
["no_data"]="нет входящих данных", | |||
["too_many_arguments"]="ожидается менее %i аргументов", | |||
["too_little_arguments"]="ожидается более %i аргументов", | |||
["wrong_calculation"]="даты %s и %s не прошли проверку, %s дней разница", | |||
["unknown_param"]="параметр %s неизвестен", | |||
["unknown_error"]="неизвестная ошибка", | |||
["tech_error"]="ошибка в функции %s", | |||
["box_date"]="строка «%s» не является верной датой, пожалуйста, укажите дату в формате ГГГГ-ММ-ДД" | |||
-- [""]="", | |||
} | |||
local tzs_names = {"ACDT","ACST","ACT","ADT","AEDT","AEST","AFT","AKDT","AKST", | local tzs_names = {"ACDT","ACST","ACT","ADT","AEDT","AEST","AFT","AKDT","AKST", | ||
Строка 59: | Строка 90: | ||
local pattern = { -- для распознавания дат, переданных одним строчным параметром | local pattern = { -- для распознавания дат, переданных одним строчным параметром | ||
{"(-?%d%d%d%d)[-%.%s/\\](%d%d)[-%.%s/\\](%d%d)", ["order"] = {3,2,1} }, -- yyyy mm dd | {"(-?%d%d%d%d?)[-%.%s/\\](%d%d)[-%.%s/\\](%d%d)", ["order"] = {3,2,1} }, -- yyyy mm dd | ||
{"(%d+)[-%.%s/\\](%d+)[-%.%s/\\](%d%d%d%d)", ["order"] = {1,2,3} }, -- dd mm yyyy | {"(%d+)[-%.%s/\\](%d+)[-%.%s/\\](%d%d%d%d?)", ["order"] = {1,2,3} }, -- dd mm yyyy | ||
{"(%d%d)[-%.%s/\\](%d%d%d%d)", ["order"] = {2,3} }, -- mm yyyy | {"(%d%d)[-%.%s/\\](%d%d%d%d?)", ["order"] = {2,3} }, -- mm yyyy | ||
{"(%d%d%d%d)[-%.%s/\\](%d%d)", ["order"] = {3,2} }, -- yyyy mm | {"(%d%d%d%d?)[-%.%s/\\](%d%d)", ["order"] = {3,2} }, -- yyyy mm | ||
{"(%d+)%s(%l+)%s(%d%d%d%d)", ["order"] = {1,2,3} }, -- d mmm y | {"(%d+)%s(%l+)%s(%d%d%d%d?)", ["order"] = {1,2,3} }, -- d mmm y | ||
{"(%l+)%s(%d%d%d%d)", | {"(%l+)%s(%d+),?%s(%d%d%d%d?)", ["order"] = {2,1,3} }, -- mmm d, y | ||
{"(%l+)%s(%d%d%d%d?)", ["order"] = {2,3} }, -- mmm y | |||
} | } | ||
Строка 73: | Строка 105: | ||
-- напоминание чтобы сделать более точные пересчёты - с часами / расчёт длительностей периодов | -- напоминание чтобы сделать более точные пересчёты - с часами / расчёт длительностей периодов | ||
local | local mnlang = {"ru_G", "ru_N", "en", "de", "fr"} | ||
local month_lang = { | local month_lang = { | ||
["ru_G"] = {"января","февраля","марта","апреля","мая","июня", | ["ru_G"] = {"января","февраля","марта","апреля","мая","июня", | ||
Строка 100: | Строка 132: | ||
-- запуск цикла по заполнению обратных таблиц, необходимых для распознавания дат | -- запуск цикла по заполнению обратных таблиц, необходимых для распознавания дат | ||
local filling_months = function ( | local filling_months = function (mnlang, month_lang) | ||
for i=1, # | for i=1, #mnlang do | ||
reverse_month_lang[ | reverse_month_lang[mnlang[i]] = reverse_table(month_lang[mnlang[i]]) | ||
end | end | ||
end | end | ||
Строка 131: | Строка 163: | ||
local function init(num) | local function init(num) | ||
output = {} | local output = {} | ||
for i=1,num do | for i=1,num do | ||
table.insert(output, {["year"]="", ["month"]="", ["day"]=""}) | table.insert(output, {["year"]="", ["month"]="", ["day"]=""}) | ||
Строка 147: | Строка 179: | ||
local function inbord(val, down, up) | local function inbord(val, down, up) | ||
return not (type(up) ~= "number" or type(down) ~= "number" or type(val) ~= "number" or up < down or val < down or val > up) | |||
end | end | ||
function shallowcopy(orig) | local function shallowcopy(orig) | ||
local orig_type = type(orig) | local orig_type = type(orig) | ||
local copy | local copy | ||
Строка 182: | Строка 210: | ||
elseif type(tbl) ~= "table" then return tbl | elseif type(tbl) ~= "table" then return tbl | ||
elseif (tbl.day or tbl.month or tbl.year) then | elseif (tbl.day or tbl.month or tbl.year) then | ||
return (tbl.year or " | return (tbl.year or "?").."-"..(tbl.month or "?").."-"..(tbl.day or "?") | ||
else return (tbl[3] or " | else return (tbl[3] or "?").."-"..(tbl[2] or "?").."-"..(tbl[1] or "?") | ||
end | end | ||
end | end | ||
Строка 209: | Строка 237: | ||
end | end | ||
function isdate ( chain , jul ) -- можно использовать для проверки таблиц с полями day, month, year | local function isdate ( chain , jul ) -- можно использовать для проверки таблиц с полями day, month, year | ||
if not chain then return false | if not chain then return false | ||
elseif (not type(chain) == "table") | elseif (not type(chain) == "table") | ||
Строка 293: | Строка 321: | ||
return math.floor(tonumber(str)) | return math.floor(tonumber(str)) | ||
else | else | ||
for i=1, # | for i=1, #mnlang do | ||
if inlist(mw.ustring.lower(str),month_lang[ | if inlist(mw.ustring.lower(str),month_lang[mnlang[i]]) then | ||
return reverse_month_lang[ | return reverse_month_lang[mnlang[i]][mw.ustring.lower(str)] | ||
end | end | ||
end | end | ||
Строка 307: | Строка 335: | ||
local error_data = {} | local error_data = {} | ||
for i=1, #pattern do | for i=1, #pattern do | ||
local result_1, result_2, result_3 = mw.ustring.match(date_string,pattern[i][1]) | local result_1, result_2, result_3 = mw.ustring.match(mw.ustring.lower(date_string),pattern[i][1]) | ||
if (result_1 or "") > "" then | if (result_1 or "") > "" then | ||
out_date_str[pattern[i].order[1]] | out_date_str[pattern[i].order[1]] = result_1 | ||
out_date_str[pattern[i].order[2]] | out_date_str[pattern[i].order[2]] = result_2 | ||
out_date_str[pattern[i].order[3]] = | if (pattern[i].order[3]) then out_date_str[pattern[i].order[3]] = result_3 end | ||
-- mw.log("Паттерн " .. i .. ", строка: " .. date_string) | |||
break | break | ||
end | end | ||
end | end | ||
local date = { | local date = { | ||
Строка 327: | Строка 352: | ||
----[[ УСТАРЕЛО ]]---- | ----[[ УСТАРЕЛО ]]---- | ||
local numstr2date = function(numstr) | local numstr2date = function(numstr) | ||
local format = "Y-m-d" | local format = "Y-m-d" | ||
local iso_date = | local iso_date = mwlang:formatDate(format,numstr) | ||
local y,m,d = string.match(iso_date, "(%d+)-(%d+)-(%d+)") | local y,m,d = string.match(iso_date, "(%d+)-(%d+)-(%d+)") | ||
local dateout = {["year"]=purif(y), ["month"]=purif(m), ["day"]=purif(d)} | local dateout = {["year"]=purif(y), ["month"]=purif(m), ["day"]=purif(d)} | ||
Строка 349: | Строка 373: | ||
-- dateout = {["year"]=nums[3], ["month"]=nums[2], ["day"]=nums[1]} | -- dateout = {["year"]=nums[3], ["month"]=nums[2], ["day"]=nums[1]} | ||
-- else | -- else | ||
-- local | -- local mwlang = mw.getContentLanguage() | ||
-- implement | -- implement mwlang:formatDate(format,datein,true) here | ||
-- return error("Не распознано " .. numstr .. " как дата") | -- return error("Не распознано " .. numstr .. " как дата") | ||
-- end | -- end | ||
Строка 364: | Строка 388: | ||
else numyear = 1 - numyear end | else numyear = 1 - numyear end | ||
if wiki then | if wiki then | ||
-- output = | -- output = tCon({'[[', numyear,' год',bcmark,'|', numyear,']]', " ", yearmark, " ", bcmark}) | ||
output = | output = tCon({'[[', numyear,' год',bcmark,'|', trim(numyear .. " " .. yearmark .. " " .. bcmark), ']]'}) | ||
else | else | ||
output = | output = tCon({numyear, " ", yearmark, bcmark}) | ||
end | end | ||
return trim(output) | return trim(output) | ||
Строка 375: | Строка 399: | ||
-- 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 | ||
local dm_separ, output = "" | local dm_separ, output = "", nil | ||
if (not (not datein.day)) and (not (not datein.month)) then dm_separ = " " end | if (not (not datein.day)) and (not (not datein.month)) then dm_separ = " " end | ||
if (not datein.month) then datein.month = "" end | if (not datein.month) then datein.month = "" end | ||
Строка 381: | Строка 405: | ||
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 = | output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "", | ||
"|", (datein.day or ""), dm_separ, monlan, "]]"}) | "|", (datein.day or ""), dm_separ, monlan, "]]"}) | ||
elseif wiki then | elseif wiki then | ||
output = | output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "", | ||
"|", (datein.day or ""), dm_separ, monlan}) | "|", (datein.day or ""), dm_separ, monlan}) | ||
else | else | ||
output = | output = tCon({datein.day, dm_separ, monlan}) | ||
end | end | ||
return trim(output) | return trim(output) | ||
Строка 400: | Строка 424: | ||
local day = purif((d or "-"):match("(%d+)")) | local day = purif((d or "-"):match("(%d+)")) | ||
if not month then | if not month then | ||
msg = category | msg = category.incomplete_parameters | ||
month = purif(month_to_num[string.lower(mw.ustring.match((d or ""),"(%a+)") or "-")]) | month = purif(month_to_num[string.lower(mw.ustring.match((d or ""),"(%a+)") or "-")]) | ||
end | end | ||
if (not day) and ((purif(string.match(m or "","(%d+)") or "") or 32) <= (monthd[month] or 31)) then | if (not day) and ((purif(string.match(m or "","(%d+)") or "") or 32) <= (monthd[month] or 31)) then | ||
msg = category | msg = category.incomplete_parameters | ||
day = purif(m:match("(%d+)") or "") | day = purif(m:match("(%d+)") or "") | ||
end | end | ||
if not year then | if not year then | ||
msg = category | msg = category.incomplete_parameters | ||
year = purif(string.match(m or "","(%d+)") or "") | year = purif(string.match(m or "","(%d+)") or "") | ||
end | end | ||
Строка 417: | Строка 441: | ||
local function glue(d1,m1,y1,d2,m2,y2) | local function glue(d1,m1,y1,d2,m2,y2) | ||
if (not d1) and (not m1) and (not y1) and (not d2) and (not m2) and (not y2) then | if (not d1) and (not m1) and (not y1) and (not d2) and (not m2) and (not y2) then | ||
return category | return category.incomplete_parameters end | ||
local gd,gm,gy,jd,jm,jy = | local gd,gm,gy,jd,jm,jy = | ||
(d1 or ""), | (d1 or ""), | ||
Строка 425: | Строка 449: | ||
(m2 or ""), | (m2 or ""), | ||
(y2 or "") | (y2 or "") | ||
--mw.log( | --mw.log(tCon({gd,gm,gy,jd,jm,jy})) | ||
local gm_sep = {" [["," год|","]]"} | local gm_sep = {" [["," год|","]]"} | ||
if (not gy) or (gy == "") then gm_sep = {"","",""} end | if (not gy) or (gy == "") then gm_sep = {"","",""} end | ||
return | return tCon({comment[1],trim(trim(jd .. " " .. jm) .. " " .. jy ), | ||
comment[2]," ([[",trim(gd .. " " .. gm),"]]",gm_sep[1],(gy:match("(%d+)") or ""), | comment[2]," ([[",trim(gd .. " " .. gm),"]]",gm_sep[1],(gy:match("(%d+)") or ""), | ||
gm_sep[2],gy,gm_sep[3],")",category | gm_sep[2],gy,gm_sep[3],")",category.incomplete_parameters}) | ||
end | end | ||
Строка 450: | Строка 474: | ||
if jd.year == gd.year then | if jd.year == gd.year then | ||
cd.year = gd.year | cd.year = gd.year | ||
gd.year, jd.year = nil | gd.year, jd.year = nil, nil | ||
end | end | ||
if jd.month == gd.month then | if jd.month == gd.month then | ||
cd.month = gd.month | cd.month = gd.month | ||
gd.month, jd.month = 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 | return tCon({comment[1] .. trim(day2lang(jd,jdate,false) .. " " .. year2lang(jd.year,yearmark,false)) .. comment[2], | ||
trim(left .. day2lang(gd,gdate,wd,wm) .. " " .. year2lang(gd.year,yearmark,wy)) .. right, | trim(left .. day2lang(gd,gdate,wd,wm) .. " " .. 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 | 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, | ||
trim(day2lang(cd,gdate,false)), trim(year2lang(cd.year,yearmark,wy)..msg)}, " ") | trim(day2lang(cd,gdate,false)), trim(year2lang(cd.year,yearmark,wy)..msg)}, " ") | ||
Строка 468: | Строка 492: | ||
-- 40) Блок функций для перевода дат с использованием [[Юлианская дата]] | -- 40) Блок функций для перевода дат с использованием [[Юлианская дата]] | ||
function gri2jd( datein ) | local function gri2jd( datein ) | ||
if not isdate(datein) then return error((datein.day or "") .. "." .. (datein.month or "") .."." .. (datein.year or "") .. " неподходящая дата") end | if not isdate(datein) then return error((datein.day or "") .. "." .. (datein.month or "") .."." .. (datein.year or "") .. " неподходящая дата") end | ||
local year = datein.year | local year = datein.year | ||
Строка 487: | Строка 511: | ||
end | end | ||
function jd2jul( jd ) | local function jd2jul( jd ) | ||
if type(jd) ~= "number" then return error("Промежуточная переменная " .. (jd or "") .. " не является числом") end | if type(jd) ~= "number" then return error("Промежуточная переменная " .. (jd or "") .. " не является числом") end | ||
-- calendar date calculation | -- calendar date calculation | ||
Строка 502: | Строка 526: | ||
end | end | ||
function jul2jd( datein ) | local function jul2jd( datein ) | ||
if not isdate(datein,true) then return error((datein.day or "") .. "." .. (datein.month or "") ..".".. (datein.year or "") .. " неподходящая дата") end | if not isdate(datein,true) then return error((datein.day or "") .. "." .. (datein.month or "") ..".".. (datein.year or "") .. " неподходящая дата") end | ||
local year = datein.year | local year = datein.year | ||
Строка 521: | Строка 545: | ||
end | end | ||
function jd2gri( jd ) | local function jd2gri( jd ) | ||
if type(jd) ~= "number" then return error("Промежуточная переменная " .. (jd or "") .. " не является числом") end | if type(jd) ~= "number" then return error("Промежуточная переменная " .. (jd or "") .. " не является числом") end | ||
-- calendar date calculation | -- calendar date calculation | ||
Строка 538: | Строка 562: | ||
end | end | ||
function astroyear(num, bc) | local function astroyear(num, bc) | ||
if not num then return error() | if not num then return error() | ||
elseif type(num) ~= "number" then return error() | elseif type(num) ~= "number" then return error() | ||
Строка 548: | Строка 572: | ||
end | end | ||
function recalc(datein,calend) | local function recalc(datein,calend) | ||
if inlist(calend,params[1]) then | if inlist(calend,params[1]) then | ||
return jd2jul(gri2jd(datein)), datein | return jd2jul(gri2jd(datein)), datein | ||
elseif inlist(calend,params[2]) then | elseif inlist(calend,params[2]) then | ||
return datein, jd2gri(jul2jd(datein)) | return datein, jd2gri(jul2jd(datein)) | ||
else error("Параметр " .. (calend or "") .. " не опознан, разрешённые: " .. | else error("Параметр " .. (calend or "") .. " не опознан, разрешённые: " .. tCon(params[1]," ") .. " и " .. tCon(params[2]," ")) | ||
end | end | ||
end | end | ||
Строка 566: | Строка 590: | ||
local cat = "" | local cat = "" | ||
local nums = {} | local nums = {} | ||
local hmarg, timedec = 0 | local hmarg, timedec = 0, 0 | ||
local mmarg = "00" | local mmarg = "00" | ||
local output = "" | local output = "" | ||
Строка 662: | Строка 686: | ||
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12 декабря 2020"}}) | -- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12 декабря 2020"}}) | ||
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"1.2.1602"}}) | -- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"1.2.1602"}}) | ||
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12.12.2021"}}) | -- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12.12.2021"}}) | ||
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"2021.12.12"}}) | -- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"2021.12.12"}}) | ||
function p.ToIso( frame ) | function p.ToIso( frame ) | ||
local args = getArgs(frame, { frameOnly = true }) | local args = getArgs(frame, { frameOnly = true }) | ||
local datein = args[1] | local datein = args[1] | ||
-- инициализация, заполнение обратных таблиц, копирование параметров | -- инициализация, заполнение обратных таблиц, копирование параметров | ||
filling_months( | filling_months(mnlang, month_lang) | ||
-- парсинг входящей даты по шаблону | -- парсинг входящей даты по шаблону | ||
local date = parse_date(datein) | local date = parse_date(datein) | ||
if not (type(date.year) == 'number') then | if not (type(date.year) == 'number') then | ||
return | return ("Wrong year: " .. unwarp(date)) | ||
end | end | ||
if not (1 <= date.month and date.month <= 12) then | if not (1 <= date.month and date.month <= 12) then | ||
return | return ("Wrong month: " .. unwarp(date)) | ||
end | end | ||
if not (1 <= date.day and date.day <= month_end_day(date.month,date.year)) then | if not date.day or not (1 <= date.day and date.day <= month_end_day(date.month,date.year)) then | ||
return | return ("Wrong day: " .. unwarp(date)) | ||
end | end | ||
local timedate = os.time{year=date.year, month=date.month, day=date.day} | local timedate = os.time{year=date.year, month=date.month, day=date.day} | ||
local date = os.date("%Y-%m-%d", timedate) | local date = os.date("%Y-%m-%d", timedate) | ||
return date | return date | ||
end | |||
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12 декабря 2020"}}) | |||
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"1.2.1602"}}) | |||
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"декабрь 2020"}}) | |||
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12-2020"}}) | |||
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12.12.2021"}}) | |||
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"2021.12.12"}}) | |||
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"2021.11"}}) | |||
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"11.2021"}}) | |||
function p.BoxDate( frame ) | |||
local args = getArgs(frame, { frameOnly = true }) | |||
local txtDateIn, strFormat = args[1], args[2] | |||
local txtDateOut, date, status = p.bxDate(txtDateIn, strFormat, params) | |||
if status.brk then | |||
return error(status.errorText) | |||
else | |||
return txtDateOut | |||
end | |||
end | |||
function p.bxDate( txtDateIn , strFormat, params ) -- к отладке | |||
local txtDateOut, date, status = "", {}, {brk = false, errorCat = "", errorText = ""} | |||
strFormat = strFormat or "j xg Y" | |||
-- заглушка - таблица параметров на будущее | |||
params = params or {} | |||
if not txtDateIn then | |||
status.errorText = e.no_data | |||
status.errorCat = category.no_parameters | |||
status.brk = true | |||
else | |||
-- заполнение служебных таблиц | |||
filling_months(mnlang, month_lang) | |||
end | |||
if not status.brk then | |||
-- парсинг входящей даты по шаблону | |||
date = parse_date(txtDateIn) | |||
-- заменить сообщения об ошибках на списочные | |||
if not (date.year and type(date.year) == 'number') then | |||
status.errorText = string.format(e.box_date,txtDateIn) | |||
status.errorCat = category.incomplete_parameters | |||
status.brk = true | |||
end | |||
if not inbord(date.month,1,12) then | |||
status.errorText = string.format(e.box_date,txtDateIn) | |||
status.errorCat = category.incomplete_parameters | |||
status.brk = true | |||
end | |||
if not date.day and string.find(strFormat,"[dDjlNwzW]") then | |||
strFormat = trim(string.gsub(string.gsub(strFormat,"xg","F"),"[dDjlNwzW]","")) | |||
elseif not date.day then | |||
elseif not inbord(date.day,1,month_end_day(date.month,date.year)) then | |||
status.errorText = string.format(e.box_date,txtDateIn) | |||
status.errorCat = category.incomplete_parameters | |||
status.brk = true | |||
end | |||
end | |||
if not status.brk then | |||
txtDateOut = mwlang:formatDate(strFormat,tCon({date.year,date.month,date.day},"-"),true) | |||
end | |||
return txtDateOut, date, status | |||
end | end | ||
function p.ToDate( frame ) -- возможно неиспользуемая | function p.ToDate( frame ) -- возможно неиспользуемая | ||
local args = getArgs(frame, { frameOnly = true }) | local args = getArgs(frame, { frameOnly = true }) | ||
local | local mwlang = mw.getContentLanguage() | ||
local datein = args[1] | local datein = args[1] | ||
local format = "j xg Y" | local format = "j xg Y" | ||
Строка 698: | Строка 779: | ||
else format = args[2] | else format = args[2] | ||
end | end | ||
return | return mwlang:formatDate(format,datein,true) | ||
end | end | ||
Строка 741: | Строка 822: | ||
local args = getArgs(frame, { frameOnly = true }) | local args = getArgs(frame, { frameOnly = true }) | ||
if not args[1] then return err end | if not args[1] then return err end | ||
local gdate, jdate = {} | local gdate, jdate = {}, {} | ||
local strin = args[1] | local strin = args[1] | ||
local cal = args[2]:lower() or "г" | local cal = args[2]:lower() or "г" | ||
Строка 796: | Строка 877: | ||
local datein = {["year"]=purif(year), ["month"]=purif(month), ["day"]=purif(day)} | local datein = {["year"]=purif(year), ["month"]=purif(month), ["day"]=purif(day)} | ||
jdate, gdate = recalc(datein,cal) | local jdate, gdate = recalc(datein,cal) | ||
local yearmark = "года" | local yearmark = "года" | ||
Строка 914: | Строка 995: | ||
mw.log("g1date " .. (undate(g1date ) or "")) | mw.log("g1date " .. (undate(g1date ) or "")) | ||
mw.log("g2date " .. (undate(g2date ) or "")) | mw.log("g2date " .. (undate(g2date ) or "")) | ||
return err .. category | return err .. category.incomplete_parameters | ||
end | end | ||
end | end | ||
return p | return p |
Текущая версия от 18:30, 19 марта 2022
Функции
Находится в бета-версии (42 273 байт). Об ошибках просьба сообщать на страницу обсуждения шаблона или самого модуля, или Carn. Если вы хотите поэкспериментировать, лучше делать это в альфа-версии (30 288 байт).
NthDay
{{ДатыСтрокой}}, {{Даты}}
- Получает 4 числовых аргумента, считает дату и выдаёт её в формате пятого, необязательного аргумента. Примеры использования (значения аргументов в скобках):
- первое (1) воскресенье (0) октября (10) (2020) года =
{{#invoke:Calendar|NthDay|1|0|10|2020}}
= 04.10.20 - вторая (2) среда (3) мая (5) (2019) года =
{{#invoke:Calendar|NthDay|2|3|5|2019}}
= 08.05.19 - последний (-1) понедельник (1) января (1) (2010) года =
{{#invoke:Calendar|NthDay|-1|1|1|2010}}
= 25.01.10 - предпоследняя (-2) суббота (6) декабря (12) (2001) года =
{{#invoke:Calendar|NthDay|-2|6|12|2001}}
= 22.12.01 - третье (3) воскресенье (0) марта (3) (2024) года в формате ISO 8601=
{{#invoke:Calendar|NthDay|3|0|3|2024|%Y-%m-%d}}
= 2024-03-17
- первое (1) воскресенье (0) октября (10) (2020) года =
unitime
- Оформляет ссылку на UTC, если есть любой второй параметр — ставит летнее время
{{#invoke:Calendar|unitime|-0}}
= UTC±0:00{{#invoke:Calendar|unitime|+0}}
= UTC±0:00{{#invoke:Calendar|unitime|+2:00}}
= UTC+2:00{{#invoke:Calendar|unitime|−3:30|}}
= UTC−3:30{{#invoke:Calendar|unitime|+12:45|1}}
= UTC+12:45, летом UTC+13:45{{#invoke:Calendar|unitime|-3:30|да}}
= UTC−3:30, летом UTC−2:30{{#invoke:Calendar|unitime|CET}}
= UTC+1:00{{#invoke:Calendar|unitime|EST|no}}
= UTC−5:00, летом UTC−4:00
OldDate
устарело
- Два обязательных аргумента, первый из которых — дата в формате ДД.ММ.ГГГГ или Д. М.ГГГГ, второй — григорианский/юлианский календарь, «г» или «ю»
- Необязательные аргументы
bc
(до нашей эры), а также параметры викификацииwd
,wm
иwy
, связанные, соответственно с вифификацией дня, месяца и года - Можно использовать параметр
sq_brts
для использования квадратных скобок и параметрyearmark
для нестандартного обозначения года{{#invoke:Calendar|OldDate|1.1.1|ю|wd=1}}
= 21 ноября (4 декабря) 2024 года ошибка!{{#invoke:Calendar|OldDate|31.12.1|г|bc=1}}
= Ошибка Lua: bad argument #2 to 'formatDate' (not a valid timestamp).{{#invoke:Calendar|OldDate|{{#time: d.m.Y }}|г}}
= 8 (21) ноября 2024 года{{#invoke:Calendar|OldDate|11.2.1602|j|wd=1|wm=0|wy=1}}
= 11 (21) февраля 1602 года{{#invoke:Calendar|OldDate|11.2.1602|j|wd=1|wm=1|wy=1}}
= 11 (21) февраля 1602 года{{#invoke:Calendar|OldDate|11.2.1602|g|bc=1|yearmark=г.}}
= 25 (11) февраля 1602 г. до н. э.{{#invoke:Calendar|OldDate|11.2.1602|g|sq_brts=1|yearmark=0}}
= 1 [11] февраля 1602
NewDate
{{DateStyle}}
- Аналогично функции выше, но может обрабатывать отрицательные даты и принимает жёстко только 2 формата d.m.y и y-m-d
{{#invoke:Calendar|NewDate|1.1.1|ю|wd=1}}
= 1 января 1 (30 декабря 1 до н. э.){{#invoke:Calendar|NewDate|31.12.1|г|bc=1}}
= 2 января 1 (31 декабря 1 до н. э.){{#invoke:Calendar|NewDate|{{#time: d.m.Y }}}}
= 8 (21) ноября 2024 (по умолчанию григорианский){{#invoke:Calendar|NewDate|11.2.1602|j|wd=1|wm=0|wy=1}}
= 11 (21) февраля 1602{{#invoke:Calendar|NewDate|11.2.1602|j|wd=1|wm=1|wy=1}}
= 11 (21) февраля 1602{{#invoke:Calendar|NewDate|11.2.1602|g|bc=1|yearmark=г.}}
= 25 (11) февраля 1602 г. до н. э.{{#invoke:Calendar|NewDate|11.2.1602|g|sq_brts=1|yearmark=0}}
= 1 [11] февраля 1602
ToIso
- Получает полную дату дату в форматах с четырёхзначным годом и выдаёт дату в формате ГГГГ-ММ-ДД
- 1.2.1602 =
{{#invoke:Calendar|ToIso|1.2.1602}}
= 1602-02-01 - -2020-12-12 =
{{#invoke:Calendar|ToIso|-2020-12-12}}
= -2020-12-12 - 5 января 1002 =
{{#invoke:Calendar|ToIso|5 января 1002}}
= 1002-01-05
- 1.2.1602 =
BoxDate
- Получает дату с четырёхзначным годом, месяцем и опционально днём месяца, выдаёт читаемую
- 06.1280 =
{{#invoke:Calendar|BoxDate|06.1280}}
= июнь 1280 - 1820-07 =
{{#invoke:Calendar|BoxDate|1820-07}}
= июль 1820 - 2020-12, xg Y =
{{#invoke:Calendar|BoxDate|2020-12|xg Y}}
= декабря 2020 - 08.08.1828 =
{{#invoke:Calendar|BoxDate|08.08.1828}}
= 8 августа 1828 - July 12, 2020 =
{{#invoke:Calendar|BoxDate|Jule 12, 2020}}
= 12 июля 2020 - 12 July 2020 =
{{#invoke:Calendar|BoxDate|12 Jule 2020}}
= 12 июля 2020 - July 2020 =
{{#invoke:Calendar|BoxDate|Jule 2020}}
= июль 2020 - 13 août 1281, l W недели Y года =
{{#invoke:Calendar|BoxDate|13 août 1281|l W недели Y года}}
= среда 33 недели 1281 года - 13 января =
{{#invoke:Calendar|BoxDate|13 января}}
= Ошибка Lua на строке 724: строка «13 января» не является верной датой, пожалуйста, укажите дату в формате ГГГГ-ММ-ДД.
- 06.1280 =
- bxDate
Реализует указанные выше функции для вызова из других модулей (см. пример использования в Message box), todo:
- поддержка отрицательных лет (запоминание знака, обработка в положительном виде, приделывание "до н.э." в конце; 0000-01-01 невалидно)
- преобразование даты в ISO формат, получение строки форматирования и преобразование по ней (необходимы доп.проверки для неточных дат)
- отдавать параметры
errorText
иerrorCat
ToDate
- Получает дату в формате Википедия:Функции парсера##time и возвращает в формате <число> <месяц в родительном падеже> <год>
- Если в строке нету символов препинания, то возвращает её неизменённой
- 1.2.1602 =
{{#invoke:Calendar|ToDate|1.2.1602}}
= 1 февраля 1602 - 1/2/1602 =
{{#invoke:Calendar|ToDate|1/2/1602}}
= 2 января 1602 - 1602-02-01 =
{{#invoke:Calendar|ToDate|1602-02-01}}
= 1 февраля 1602 - 1 февраля 1602 =
{{#invoke:Calendar|ToDate|1 февраля 1602}}
= 1 февраля 1602 - Завтра (+ 1 day) =
{{#invoke:Calendar|ToDate|+ 1 day}}
= 23 ноября 2024
- 1.2.1602 =
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 = {"января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"}
local month_to_num = {["января"]=1,["февраля"]=2,["марта"]=3,["апреля"]=4,["мая"]=5,["июня"]=6,
["июля"]=7,["августа"]=8,["сентября"]=9,["октября"]=10,["ноября"]=11,["декабря"]=12,["-"]=""}
local monthd = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
local params = { {"г", "g"}, {"ю", "j"}}
local comment = { '<span style="border-bottom: 1px dotted; cursor: help" title="по юлианскому календарю">','</span>'}
-- duplicates:
-- AST, BST, CST, ECT, IST, MST, PST, SST,
local known_tzs = {
ACDT='+10:30', ACST='+09:30', ACT ='+08:00', ADT ='-03:00', AEDT ='+11:00',
AEST='+10:00', AFT ='+04:30', AKDT='-08:00', AKST ='-09:00', AMST ='+05:00',
AMT ='+04:00', ART ='-03:00', AST ='+03:00', AST ='+04:00', AST ='+03:00',
AST ='-04:00', AWDT='+09:00', AWST='+08:00', AZOST='-01:00', AZT ='+04:00',
BDT ='+08:00', BIOT='+06:00', BIT ='-12:00', BOT ='-04:00', BRT ='-03:00',
BST ='+06:00', BST ='+01:00', BTT ='+06:00', CAT ='+02:00', CCT ='+06:30',
CDT ='-05:00', CEDT='+02:00', CEST='+02:00', CET ='+01:00', CHAST='+12:45',
CIST='-08:00', CKT ='-10:00', CLST='-03:00', CLT ='-04:00', COST ='-04:00',
COT ='-05:00', CST ='-06:00', CST ='+08:00', CVT ='-01:00', CXT ='+07:00',
CHST='+10:00', DFT ='+01:00', EAST='-06:00', EAT ='+03:00', ECT ='-04:00',
ECT ='-05:00', EDT ='-04:00', EEDT='+03:00', EEST ='+03:00', EET ='+02:00',
EST ='-05:00', FJT ='+12:00', FKST='-03:00', FKT ='-04:00', GALT ='-06:00',
GET ='+04:00', GFT ='-03:00', GILT='+12:00', GIT ='-09:00', GMT ='+00:00',
GST ='-02:00', GYT ='-04:00', HADT='-09:00', HAST ='-10:00', HKT ='+08:00',
HMT ='+05:00', HST ='-10:00', IRKT='+08:00', IRST ='+03:30', IST ='+05:30',
IST ='+01:00', IST ='+02:00', JST ='+09:00', KRAT ='+07:00', KST ='+09:00',
LHST='+10:30', LINT='+14:00', MAGT='+11:00', MDT ='-06:00', MIT ='-09:30',
MSD ='+04:00', MSK ='+03:00', MST ='+08:00', MST ='-07:00', MST ='+06:30',
MUT ='+04:00', NDT ='-02:30', NFT ='+11:30', NPT ='+05:45', NST ='-03:30',
NT ='-03:30', OMST='+06:00', PDT ='-07:00', PETT ='+12:00', PHOT ='+13:00',
PKT ='+05:00', PST ='-08:00', PST ='+08:00', RET ='+04:00', SAMT ='+04:00',
SAST='+02:00', SBT ='+11:00', SCT ='+04:00', SLT ='+05:30', SST ='-11:00',
SST ='+08:00', TAHT='-10:00', THA ='+07:00', UTC ='+00:00', UYST ='-02:00',
UYT ='-03:00', VET ='-04:30', VLAT='+10:00', WAT ='+01:00', WEDT ='+01:00',
WEST='+01:00', WET ='+00:00', YAKT='+09:00', YEKT ='+05:00',
-- US Millitary (for RFC-822)
Z='+00:00', A='-01:00', M='-12:00', N='+01:00', Y='+12:00',
}
local category = {
["no_parameters"]=
"<!--[[Категория:Модуль:Calendar:Страницы без параметров]]-->",
["incomplete_parameters"]=
"<!--[[Категория:Модуль:Calendar:Страницы с неполными или некорректными параметрами]]-->",
["without_verification"]=
"<!--[[Категория:Модуль:Calendar:Страницы без проверки параметров]]-->",
["erroneous_parameters"]=
"<!--[[Категория:Модуль:Calendar:Страницы с ошибочными параметрами]]-->"
}
-- несколько параметров передаются вместе с кодом ошибки в таблице, один может быть передан простым значением
local e = {
["start"]="<span class=error>Ошибка: ",
["ending"]=".</span>",
["no_pattern_match"]="строка «%s» не совпадает с заданными паттернами",
["no_valid_date"]="дата «%s» не является корректной",
["wrong_jd"]="юлианская дата %s вне диапазона",
["no_data"]="нет входящих данных",
["too_many_arguments"]="ожидается менее %i аргументов",
["too_little_arguments"]="ожидается более %i аргументов",
["wrong_calculation"]="даты %s и %s не прошли проверку, %s дней разница",
["unknown_param"]="параметр %s неизвестен",
["unknown_error"]="неизвестная ошибка",
["tech_error"]="ошибка в функции %s",
["box_date"]="строка «%s» не является верной датой, пожалуйста, укажите дату в формате ГГГГ-ММ-ДД"
-- [""]="",
}
local tzs_names = {"ACDT","ACST","ACT","ADT","AEDT","AEST","AFT","AKDT","AKST",
"AMST","AMT","ART","AST","AST","AST","AST","AWDT","AWST","AZOST","AZT","BDT",
"BIOT","BIT","BOT","BRT","BST","BST","BTT","CAT","CCT","CDT","CEDT","CEST",
"CET","CHAST","CIST","CKT","CLST","CLT","COST","COT","CST","CST","CVT","CXT",
"CHST","DFT","EAST","EAT","ECT","ECT","EDT","EEDT","EEST","EET","EST","FJT",
"FKST","FKT","GALT","GET","GFT","GILT","GIT","GMT","GST","GYT","HADT","HAST",
"HKT","HMT","HST","IRKT","IRST","IST","IST","IST","JST","KRAT","KST","LHST",
"LINT","MAGT","MDT","MIT","MSD","MSK","MST","MST","MST","MUT","NDT","NFT",
"NPT","NST","NT","OMST","PDT","PETT","PHOT","PKT","PST","PST","RET","SAMT",
"SAST","SBT","SCT","SLT","SST","SST","TAHT","THA","UTC","UYST","UYT","VET",
"VLAT","WAT","WEDT","WEST","WET","YAKT","YEKT","Z","A","M","N","Y","MSK"}
local pattern = { -- для распознавания дат, переданных одним строчным параметром
{"(-?%d%d%d%d?)[-%.%s/\\](%d%d)[-%.%s/\\](%d%d)", ["order"] = {3,2,1} }, -- yyyy mm dd
{"(%d+)[-%.%s/\\](%d+)[-%.%s/\\](%d%d%d%d?)", ["order"] = {1,2,3} }, -- dd mm yyyy
{"(%d%d)[-%.%s/\\](%d%d%d%d?)", ["order"] = {2,3} }, -- mm yyyy
{"(%d%d%d%d?)[-%.%s/\\](%d%d)", ["order"] = {3,2} }, -- yyyy mm
{"(%d+)%s(%l+)%s(%d%d%d%d?)", ["order"] = {1,2,3} }, -- d mmm y
{"(%l+)%s(%d+),?%s(%d%d%d%d?)", ["order"] = {2,1,3} }, -- mmm d, y
{"(%l+)%s(%d%d%d%d?)", ["order"] = {2,3} }, -- mmm y
}
local time_units = {"year","month","day"} --не используется
--[[ local time_units = {"second", "minute", "hour",
"day_of_month", "day_of_week", "day_of_year",
"week", "month", "year", "year_of_century", "century"} ]]--
-- напоминание чтобы сделать более точные пересчёты - с часами / расчёт длительностей периодов
local mnlang = {"ru_G", "ru_N", "en", "de", "fr"}
local month_lang = {
["ru_G"] = {"января","февраля","марта","апреля","мая","июня",
"июля","августа","сентября","октября","ноября","декабря"},
["ru_N"] = {"январь","февраль","март","апрель","май","июнь",
"июль","август","сентябрь","октябрь","ноябрь","декабрь"},
["en"] = {"january", "february", "march", "april", "may", "june",
"july", "august", "september", "october", "november", "december"},
["de"] = {"januar", "februar", "märz", "april", "mai", "juni",
"juli", "august", "september", "oktober", "november", "dezember"},
["fr"] = {"janvier", "février", "mars", "avril", "mai", "juin",
"juillet", "août", "septembre", "octobre", "novembre", "décembre"}
}
-- заполняется автоматически
local reverse_month_lang = {}
-- вспомогательная функция для обращения таблиц (смена ключей со значениями)
local reverse_table = function (strait_table)
local reversed_table = {}
for k,v in pairs(strait_table) do
reversed_table[v] = k
end
return reversed_table
end
-- запуск цикла по заполнению обратных таблиц, необходимых для распознавания дат
local filling_months = function (mnlang, month_lang)
for i=1, #mnlang do
reverse_month_lang[mnlang[i]] = reverse_table(month_lang[mnlang[i]])
end
end
-- 10) Блок общих функций
local function trim(str)
if not str then return nil
else return str:match'^()%s*$' and '' or str:match'^%s*(.*%S)'
end
end
local function purif(str)
if str == "" or str == nil then
return nil
elseif type(tonumber(str)) == "number" then
return math.floor(tonumber(str))
else
return nil
end
-- need .5 -- ,5 number format converter?
end
local function is(str)
if (not str) or (str == "") then return false
else return yesno(str,false)
end
end
local function init(num)
local output = {}
for i=1,num do
table.insert(output, {["year"]="", ["month"]="", ["day"]=""})
end
return unpack(output)
end
local function isyear(tbl)
if type(tbl) ~= 'table' then return false
elseif not tbl["year"] then return false
elseif type(tbl["year"]) == 'number' then return true
else return false
end
end
local function inbord(val, down, up)
return not (type(up) ~= "number" or type(down) ~= "number" or type(val) ~= "number" or up < down or val < down or val > up)
end
local function shallowcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in pairs(orig) do
copy[orig_key] = orig_value
end
else -- number, string, boolean, etc
copy = orig
end
return copy
end
local inlist = function ( var, list )
local n = #list
local inlist = false
for i=1,n do
if var == list[i] then inlist = true end
end
return inlist
end
-- 20) Блок общих проверочных функций, связанных с датами
local function unwarp(tbl)
if not tbl then return ""
elseif type(tbl) ~= "table" then return tbl
elseif (tbl.day or tbl.month or tbl.year) then
return (tbl.year or "?").."-"..(tbl.month or "?").."-"..(tbl.day or "?")
else return (tbl[3] or "?").."-"..(tbl[2] or "?").."-"..(tbl[1] or "?")
end
end
local function leap_year(y,jul)
if (not y) or (type(y) ~= "number")
then return false
elseif (y % 4) ~= 0
then return false
elseif not jul and (y % 100 == 0 and y % 400 ~= 0)
then return false
else return true
end
end
-- функция для вычисления последнего дня месяца для юлианского и григорианского календарей
local function month_end_day (month,year,is_julian)
local month_end_day = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} -- если не задан год, дата 29 февраля считается допустимой
if not month or type(month) ~= "number" or month < 1 or month > 12 then return nil
elseif month ~= 2 or not year then return month_end_day[month]
elseif month == 2 and (year % 4) == 0 and not ((not is_julian) and (year % 100 == 0 and year % 400 ~= 0)) then return 29
elseif month == 2 then return 28
else return nil -- в случае не целого значения входящих параметров или при иных непредусмотренных событиях
end
end
local function isdate ( chain , jul ) -- можно использовать для проверки таблиц с полями day, month, year
if not chain then return false
elseif (not type(chain) == "table")
or (not inbord(chain.year,-9999,9999))
or (not inbord(chain.month,1,12))
or (not inbord(chain.day,1,31))
or chain.day > monthd[chain.month]
-- or chain.year == 0
then return false
elseif chain.month == 2 and chain.day == 29 and not leap_year(chain.year,jul)
then return false
else return true end
-- check for other calendars needed?
end
local function ispartdate ( chain )
if not chain then return false
elseif not (type(chain) == "table") then return false
elseif (inbord(chain.year,-9999,9999)
or inbord(chain.month,1,12)
or inbord(chain.day,1,31)) then return true
else return false
end
-- partial date
-- more detailed check for 31.02.0000 needed
-- check for other calendars needed
end
-- from date1 to date2 in one year (beetwen jan-dec, dec-jan needed)
local function partdist(date1,date2)
local mont, dist = 0, 0
local d1d, d1m, d2d, d2m = (date1["day"] or ""), (date1["month"] or ""),(date2["day"] or ""), (date2["month"] or "")
if not (inbord(d1d,1,31) and inbord(d2d,1,31)) then return false end
-- нужна доп. проверка частичных дат на корректность
if (inbord(d1m,1,12) or inbord(d2m,1,12))
and (d1m == "" or d2m == "") then
mont = purif(date1["month"] or date2["month"])
d1m, d2m = mont, mont
end
-- mw.log("📏 day: " ..d1d .."->"..d2d.." month: ".. d1m.."->"..d2m )
if (inbord(d1m,1,12) and d1d <= monthd[d1m])
and (inbord(d2m,1,12) and d2d <= monthd[d2m]) then
if d2m == d1m
then dist = d2d - d1d
else dist = monthd[d1m] - d1d + d2d
end
return dist
else return math.huge
end
end
local function dmdist(d1,d2)
local p1,p2 = math.huge,math.huge
if not not partdist(d1,d2) then
p1=partdist(d1,d2)
end
if not not partdist(d2,d1) then
p1=partdist(d2,d1)
end
-- if (not p1) or (not p2) then
-- return (p1 or "") .. (p2 or "")
-- else
-- mw.log("d1, d2 = " .. undate(d1) .. ", " .. undate(d2))
return math.min(tonumber(partdist(d1,d2)) or math.huge,tonumber(partdist(d2,d1)) or math.huge)
-- end
end
-- 30) Блок функций для обработки ввода-вывода дат
local function undate(tbl)
if not tbl then return ""
else return (tbl.year or "").."-"..(tbl.month or "").."-"..(tbl.day or "")
end
end
-- функция для нормализации значений дат и перевода месяцев в числа
local function numerize(str)
if type(str) == "number" then
return math.floor(str)
elseif str == "" or str == nil or type(str) ~= "string" then
return nil
elseif type(tonumber(str)) == "number" then
return math.floor(tonumber(str))
else
for i=1, #mnlang do
if inlist(mw.ustring.lower(str),month_lang[mnlang[i]]) then
return reverse_month_lang[mnlang[i]][mw.ustring.lower(str)]
end
end
end
end
-- функция распознавания даты, переданной одной строкой
local function parse_date(date_string)
if type(date_string) ~= "string" or date_string == "" then return nil end
local out_date_str = {"","",""}
local error_data = {}
for i=1, #pattern do
local result_1, result_2, result_3 = mw.ustring.match(mw.ustring.lower(date_string),pattern[i][1])
if (result_1 or "") > "" then
out_date_str[pattern[i].order[1]] = result_1
out_date_str[pattern[i].order[2]] = result_2
if (pattern[i].order[3]) then out_date_str[pattern[i].order[3]] = result_3 end
-- mw.log("Паттерн " .. i .. ", строка: " .. date_string)
break
end
end
local date = {
["day"] =numerize(out_date_str[1]),
["month"]=numerize(out_date_str[2]),
["year"] =numerize(out_date_str[3])}
return date --, error_data
end
----[[ УСТАРЕЛО ]]----
local numstr2date = function(numstr)
local format = "Y-m-d"
local iso_date = mwlang:formatDate(format,numstr)
local y,m,d = string.match(iso_date, "(%d+)-(%d+)-(%d+)")
local dateout = {["year"]=purif(y), ["month"]=purif(m), ["day"]=purif(d)}
return dateout
end
--local numstr2date = function(numstr)
-- local nums = {}
-- local dateout = {}
-- for num in string.gmatch(numstr,"(%d+)") do
-- table.insert(nums,purif(num))
-- end
-- if #nums ~= 3 then error("В поле даты вместо трёх чисел с разделителями указано " .. #nums)
-- elseif not inbord(nums[2],1,12) then error("Месяц с номером " .. nums[2] .. " не найден")
-- elseif not inbord(nums[3],1,31) then
-- dateout = {["year"]=nums[3], ["month"]=nums[2], ["day"]=nums[1]}
-- elseif not inbord(nums[1],1,31) then
-- dateout = {["year"]=nums[1], ["month"]=nums[2], ["day"]=nums[3]}
-- elseif inbord(nums[1],1,31) then
-- dateout = {["year"]=nums[3], ["month"]=nums[2], ["day"]=nums[1]}
-- else
-- local mwlang = mw.getContentLanguage()
-- implement mwlang:formatDate(format,datein,true) here
-- return error("Не распознано " .. numstr .. " как дата")
-- end
-- return dateout
--end
local function year2lang(numyear,yearmark,wiki)
if not numyear then return "" end
if not yearmark then yearmark = "" end
local output = ""
local bcmark = " до н. э."
if numyear > 0 then bcmark = ""
else numyear = 1 - numyear end
if wiki then
-- output = tCon({'[[', numyear,' год',bcmark,'|', numyear,']]', " ", yearmark, " ", bcmark})
output = tCon({'[[', numyear,' год',bcmark,'|', trim(numyear .. " " .. yearmark .. " " .. bcmark), ']]'})
else
output = tCon({numyear, " ", yearmark, bcmark})
end
return trim(output)
end
local function day2lang(datein,wikidate,wiki,inner_brt)
-- if not isdate(wikidate) then wiki = false end
if not ispartdate(datein) then return "" end
local dm_separ, output = "", nil
if (not (not datein.day)) and (not (not datein.month)) then dm_separ = " " end
if (not datein.month) then datein.month = "" end
if (not datein.day) then datein.day = "" end
local monlan = monthlang[datein.month] or ""
if wiki and not inner_brt then
output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "",
"|", (datein.day or ""), dm_separ, monlan, "]]"})
elseif wiki then
output = tCon({"[[", wikidate.day, " ", monthlang[wikidate.month] or "",
"|", (datein.day or ""), dm_separ, monlan})
else
output = tCon({datein.day, dm_separ, monlan})
end
return trim(output)
end
local function triple_txt2date(d,m,y)
-- добавить (args[1]:match("(%a+)") or "-") для нестандартной записи
-- mw.ustring.match((m or ""),"(%a+)")
local msg = ""
local year = purif((y or "-"):match("(%d+)"))
local month = purif(month_to_num[string.lower(mw.ustring.match((m or ""),"(%a+)"))])
local day = purif((d or "-"):match("(%d+)"))
if not month then
msg = category.incomplete_parameters
month = purif(month_to_num[string.lower(mw.ustring.match((d or ""),"(%a+)") or "-")])
end
if (not day) and ((purif(string.match(m or "","(%d+)") or "") or 32) <= (monthd[month] or 31)) then
msg = category.incomplete_parameters
day = purif(m:match("(%d+)") or "")
end
if not year then
msg = category.incomplete_parameters
year = purif(string.match(m or "","(%d+)") or "")
end
local dateout = {["year"]=year, ["month"]=month, ["day"]=day, ["msg"]=msg}
return dateout
end
local function glue(d1,m1,y1,d2,m2,y2)
if (not d1) and (not m1) and (not y1) and (not d2) and (not m2) and (not y2) then
return category.incomplete_parameters end
local gd,gm,gy,jd,jm,jy =
(d1 or ""),
(m1 or ""),
(y1 or ""),
(d2 or ""),
(m2 or ""),
(y2 or "")
--mw.log(tCon({gd,gm,gy,jd,jm,jy}))
local gm_sep = {" [["," год|","]]"}
if (not gy) or (gy == "") then gm_sep = {"","",""} end
return tCon({comment[1],trim(trim(jd .. " " .. jm) .. " " .. jy ),
comment[2]," ([[",trim(gd .. " " .. gm),"]]",gm_sep[1],(gy:match("(%d+)") or ""),
gm_sep[2],gy,gm_sep[3],")",category.incomplete_parameters})
end
-- добавить отображение без года
local function double_couple(jdate, gdate, wd, wm, wy, sq_brts, yearmark)
local msg = ""
msg = (jdate.msg or "") .. (gdate.msg or "")
local cd = {}
local jd = shallowcopy(jdate)
local gd = shallowcopy(gdate)
local left = "("
local right = ")"
if sq_brts then
left = "["
right = "]"
end
if (not isdate(jdate,true)) then return error((jdate.day or "") .. "." .. (jdate.month or "") .."." .. (jdate.year or "") .. " неподходящая дата")
elseif (not isdate(gdate)) then return error((gdate.day or "") .. "." .. (gdate.month or "") .."." .. (gdate.year or "") .. " неподходящая дата") end
if jd.year == gd.year then
cd.year = gd.year
gd.year, jd.year = nil, nil
end
if jd.month == gd.month then
cd.month = gd.month
gd.month, jd.month = nil, nil
end
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(left .. day2lang(gd,gdate,wd,wm) .. " " .. year2lang(gd.year,yearmark,wy)) .. right,
day2lang(cd,gdate,false) .. "]]", trim(year2lang(cd.year,yearmark,wy)..msg)}, " ")
end
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(day2lang(cd,gdate,false)), trim(year2lang(cd.year,yearmark,wy)..msg)}, " ")
end
-- 40) Блок функций для перевода дат с использованием [[Юлианская дата]]
local function gri2jd( datein )
if not isdate(datein) then return error((datein.day or "") .. "." .. (datein.month or "") .."." .. (datein.year or "") .. " неподходящая дата") end
local year = datein.year
local month = datein.month
local day = datein.day
-- jd calculation
local a = math.floor((14 - month)/12)
local y = year + 4800 - a
local m = month + 12*a - 3
local offset = math.floor(y/4) - math.floor(y/100) + math.floor(y/400) - 32045
local jd = day + math.floor((153*m + 2)/5) + 365*y + offset
-- jd validation
local low, high = -1931076.5, 5373557.49999
if not (low <= jd and jd <= high) then
return error((datein.day or "") .. "." .. (datein.month or "") .. "." .. (datein.year or "") .. " выходит за пределы разрешённого диапазона")
end
return jd
end
local function jd2jul( jd )
if type(jd) ~= "number" then return error("Промежуточная переменная " .. (jd or "") .. " не является числом") end
-- calendar date calculation
local c = jd + 32082
local d = math.floor((4*c + 3)/1461)
local e = c - math.floor(1461*d/4)
local m = math.floor((5*e + 2)/153)
local year_out = d - 4800 + math.floor(m/10)
local month_out = m + 3 - 12*math.floor(m/10)
local day_out = e - math.floor((153*m + 2)/5) + 1
-- output
local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out}
return dateout
end
local function jul2jd( datein )
if not isdate(datein,true) then return error((datein.day or "") .. "." .. (datein.month or "") ..".".. (datein.year or "") .. " неподходящая дата") end
local year = datein.year
local month = datein.month
local day = datein.day
-- jd calculation
local a = math.floor((14 - month)/12)
local y = year + 4800 - a
local m = month + 12*a - 3
local offset = math.floor(y/4) - 32083
local jd = day + math.floor((153*m + 2)/5) + 365*y + offset
-- jd validation
local low, high = -1930999.5, 5373484.49999
if not (low <= jd and jd <= high) then
return error((datein.day or "") .. "." .. (datein.month or "") .."." .. (datein.year or "") .. " выходит за пределы разрешённого диапазона")
end
return jd
end
local function jd2gri( jd )
if type(jd) ~= "number" then return error("Промежуточная переменная " .. (jd or "") .. " не является числом") end
-- calendar date calculation
local a = jd + 32044
local b = math.floor((4*a + 3) / 146097)
local c = a - math.floor(146097*b/4)
local d = math.floor((4*c+3)/1461)
local e = c - math.floor(1461*d/4)
local m = math.floor((5*e+2)/153)
local day_out = e - math.floor((153*m+2)/5)+1
local month_out = m + 3 - 12*math.floor(m/10)
local year_out = 100*b + d - 4800 + math.floor(m/10)
-- output
local dateout = {["year"]=year_out, ["month"]=month_out, ["day"]=day_out}
return dateout
end
local function astroyear(num, bc)
if not num then return error()
elseif type(num) ~= "number" then return error()
end
if num < 1 then return num end
if not bc then return num
else return 1 - num
end
end
local function recalc(datein,calend)
if inlist(calend,params[1]) then
return jd2jul(gri2jd(datein)), datein
elseif inlist(calend,params[2]) then
return datein, jd2gri(jul2jd(datein))
else error("Параметр " .. (calend or "") .. " не опознан, разрешённые: " .. tCon(params[1]," ") .. " и " .. tCon(params[2]," "))
end
end
-- 50) Функции для обработки UTC
local function utc(str,margin)
local d = 1
local dchar = "+"
local beginning = "[[UTC"
local ending = "]]"
local cat = ""
local nums = {}
local hmarg, timedec = 0, 0
local mmarg = "00"
local output = ""
-- checking type of input
if not margin then margin = 0
elseif type(tonumber(margin)) ~= 'number' then
output = "Can't shift by " .. margin
error(output)
end
if type(str) ~= 'string' then
error("Нет входящей строки")
elseif str:byte(1) == 43 then
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
else
error(string.char(str:byte(1)) .. " недопустимый первый символ")
end
-- parsing input
for num in string.gmatch(str,"(%d+)") do
table.insert(nums,purif(num))
end
if #nums > 2 then error("Ожидается всего 2 числа, а не " .. #nums)
elseif #nums == 0 then error("Необходимо что-то ввести")
elseif #nums == 1 then
if inbord(nums[1],0,14) then timedec = d*nums[1] + margin
else error("Только часы от -14 до 14") end
elseif #nums == 2 then
if not inbord(nums[1],0,14) then error("Только часы от -14 до 14")
elseif not inbord(nums[2],0,59) then error("Минуты только от 0 до 59")
else
timedec = d*(nums[1] + nums[2]/60) + margin
end
end
if tonumber(timedec) == purif(timedec) then hmarg = timedec
else
local h, m = math.modf(math.abs(timedec))
hmarg = h
mmarg = math.floor(m*60)
end
if timedec == 0 then
dchar = "±"
elseif timedec > 0 then
elseif timedec < 0 then
dchar = "−"
end
-- output
output = beginning .. dchar .. math.abs(hmarg) .. ":" .. string.format("%02d",mmarg) .. ending .. cat
return output
end
-- 60) Блок функций ввода-вывода
function p.NthDay( frame )
local args = getArgs(frame, { frameOnly = true })
local num, wday, mont, yea, format =
purif(args[1]), purif(args[2]), purif(args[3]), purif(args[4]), args[5]
if not format then format = "%d.%m.%y" end
if not inbord(num,-5,5) then
return error("The number must be between -5 and 5")
elseif num == 0 then
return error("The number must not be zero") end
if not inbord(wday,0,6) then
return error("The day of the week must be between 0 and 6") end
if not inbord(mont,1,12) then
return error("The month must be between 1 and 12") end
if not inbord(yea,0,9999) then
return error("Wrong year number") end
if inbord(num,1,5) then
local m_start = os.time{year=yea, month=mont, day=1, hour=0}
local m_wds = tonumber(os.date("%w", m_start))
local start_shift = (
(num - bool_to_number[wday >= m_wds]) * 7
- (m_wds - wday)
) * 24 * 60 * 60
local tim = m_start + start_shift
if tonumber(os.date("%m", tim)) == mont then
return (os.date(format, tim))
else
return (err)
end
elseif inbord(num,-5,-1) then
local m_end = os.time{year = yea, month = mont + 1, day = 1, hour = 0} - 24 * 60 * 60
local m_wde = tonumber(os.date("%w", m_end))
local end_shift = ((math.abs(num + 1) + bool_to_number[wday > m_wde]) * 7
+ (m_wde - wday)) * 24 * 60 * 60
local tim = m_end - end_shift
if tonumber(os.date("%m", tim)) == mont then
return (os.date(format, tim))
else
return (err)
end
end
end
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12 декабря 2020"}})
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"1.2.1602"}})
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12.12.2021"}})
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"2021.12.12"}})
function p.ToIso( frame )
local args = getArgs(frame, { frameOnly = true })
local datein = args[1]
-- инициализация, заполнение обратных таблиц, копирование параметров
filling_months(mnlang, month_lang)
-- парсинг входящей даты по шаблону
local date = parse_date(datein)
if not (type(date.year) == 'number') then
return ("Wrong year: " .. unwarp(date))
end
if not (1 <= date.month and date.month <= 12) then
return ("Wrong month: " .. unwarp(date))
end
if not date.day or not (1 <= date.day and date.day <= month_end_day(date.month,date.year)) then
return ("Wrong day: " .. unwarp(date))
end
local timedate = os.time{year=date.year, month=date.month, day=date.day}
local date = os.date("%Y-%m-%d", timedate)
return date
end
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12 декабря 2020"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"1.2.1602"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"декабрь 2020"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12-2020"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"12.12.2021"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"2021.12.12"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"2021.11"}})
-- =p.BoxDate(mw.getCurrentFrame():newChild{title="smth",args={"11.2021"}})
function p.BoxDate( frame )
local args = getArgs(frame, { frameOnly = true })
local txtDateIn, strFormat = args[1], args[2]
local txtDateOut, date, status = p.bxDate(txtDateIn, strFormat, params)
if status.brk then
return error(status.errorText)
else
return txtDateOut
end
end
function p.bxDate( txtDateIn , strFormat, params ) -- к отладке
local txtDateOut, date, status = "", {}, {brk = false, errorCat = "", errorText = ""}
strFormat = strFormat or "j xg Y"
-- заглушка - таблица параметров на будущее
params = params or {}
if not txtDateIn then
status.errorText = e.no_data
status.errorCat = category.no_parameters
status.brk = true
else
-- заполнение служебных таблиц
filling_months(mnlang, month_lang)
end
if not status.brk then
-- парсинг входящей даты по шаблону
date = parse_date(txtDateIn)
-- заменить сообщения об ошибках на списочные
if not (date.year and type(date.year) == 'number') then
status.errorText = string.format(e.box_date,txtDateIn)
status.errorCat = category.incomplete_parameters
status.brk = true
end
if not inbord(date.month,1,12) then
status.errorText = string.format(e.box_date,txtDateIn)
status.errorCat = category.incomplete_parameters
status.brk = true
end
if not date.day and string.find(strFormat,"[dDjlNwzW]") then
strFormat = trim(string.gsub(string.gsub(strFormat,"xg","F"),"[dDjlNwzW]",""))
elseif not date.day then
elseif not inbord(date.day,1,month_end_day(date.month,date.year)) then
status.errorText = string.format(e.box_date,txtDateIn)
status.errorCat = category.incomplete_parameters
status.brk = true
end
end
if not status.brk then
txtDateOut = mwlang:formatDate(strFormat,tCon({date.year,date.month,date.day},"-"),true)
end
return txtDateOut, date, status
end
function p.ToDate( frame ) -- возможно неиспользуемая
local args = getArgs(frame, { frameOnly = true })
local mwlang = mw.getContentLanguage()
local datein = args[1]
local format = "j xg Y"
if not string.match(datein, "%p") then return datein
elseif not args[2] then
else format = args[2]
end
return mwlang:formatDate(format,datein,true)
end
-- =p.unitime(mw.getCurrentFrame():newChild{title="smth",args={"−1:30","1"}})
function p.unitime( frame )
local args = getArgs(frame, { frameOnly = true })
local DST = 0
if not args[2] then
else DST = 1 end
local utcin = ""
local input = args[1]
if not input then return "" end
if inlist(input:upper(),tzs_names) then
utcin = known_tzs[input:upper()]
elseif (string.sub(input:upper(),1,3) == 'UTC') and (string.len(input) < 10) then
utcin = string.sub(input,4)
else
if string.sub(input,1,1) == '['
or string.sub(input,1,1) == '{'
or string.sub(input,1,1):upper() == 'U'
or string.sub(input,1,1):upper() == 'M' then
return input
-- elseif not string.find(string.upper(string.sub(input,1,1)),"[\65-\90]") or
-- not string.find(string.upper(string.sub(input,1,1)),"[\192-\223]") then
-- return input
else utcin = input end
end
-- elseif string.sub(input,1,3) ~= "−" then utcin = input
-- or not (not input:find("[А-я]")) при наличии в строке юникода не работает
local output = ""
if DST == 0 then output = utc(utcin)
else output = utc(utcin) .. ", [[летнее время|летом]] " .. utc(utcin,DST)
end
return output
end
-- УСТАРЕЛО
-- =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 )
local args = getArgs(frame, { frameOnly = true })
if not args[1] then return err end
local gdate, jdate = {}, {}
local strin = args[1]
local cal = args[2]:lower() or "г"
local bc = is(args["bc"])
local wd = is(args["wd"])
local wm = is(args["wm"])
local wy = is(args["wy"])
if not wd then wm = false end
local sq_brts = is(args["sq_brts"])
local yearmark = "года"
if yesno(args["yearmark"]) then
elseif yesno(args["yearmark"]) == false then yearmark = ""
else yearmark = trim(args["yearmark"]) or "года" end
-- local infocard = is(args["infocard"])
-- local catName = args["catName"] or false
local datein = numstr2date(strin)
datein.year = astroyear(datein.year, bc)
jdate, gdate = recalc(datein,cal)
return double_couple(jdate, gdate, wd, wm, wy, sq_brts, yearmark)
end
-- =p.NewDate(mw.getCurrentFrame():newChild{title="Salt",args={"2020-02-20"}})
-- =p.NewDate(mw.getCurrentFrame():newChild{title="smth",args={"20.02.2020","ю",["bc"]="1",["wd"]="1",["wy"]="1",["sq_brts"]="1",["yearmark"]="г."}})
-- =p.NewDate(mw.getCurrentFrame():newChild{title="smth",args={"20.02.2020",["bc"]="0",["wd"]="1",["wy"]="1",["sq_brts"]="0",["yearmark"]=""}})
function p.NewDate( frame )
local args = getArgs(frame, { frameOnly = true })
if not args[1] then return err end
local strin = args[1]
local year, month, day
if not not strin:match( "(-?%d%d%d%d%d)-(%d%d)-(%d%d)" ) then
year, month, day = strin:match( "(-?%d%d%d%d%d)-(%d%d)-(%d%d)" )
elseif not not strin:match( "(-?%d+)-(%d+)-(%d+)" ) then
year, month, day = strin:match( "(-?%d+)-(%d+)-(%d+)" )
elseif not not strin:match( "(%d%d)%.(%d%d)%.(-?%d%d%d%d%d)" ) then
day, month, year = strin:match( "(%d%d)%.(%d%d)%.(-?%d%d%d%d%d)" )
elseif not not strin:match( "(%d+)%.(%d+)%.(-?%d+)" ) then
day, month, year = strin:match( "(%d+)%.(%d+)%.(-?%d+)" )
end
if not year then return error(args[1] .. " не подходит под форматы yyyy-mm-dd или dd.mm.yyyy")
end
local cal = "г"
if (not args[2]) or (args[2] == "") then cal = "г"
else cal = args[2]:lower() end
local bc,wd,wm,wy,sq_brts =
is(args["bc"]),
is(args["wd"]),
is(args["wd"]) and is(args["wm"]),
is(args["wy"]),
is(args["sq_brts"])
year = astroyear(purif(year),bc)
local datein = {["year"]=purif(year), ["month"]=purif(month), ["day"]=purif(day)}
local jdate, gdate = recalc(datein,cal)
local yearmark = "года"
local ym = args["yearmark"] or ""
if yesno(ym) then
elseif yesno(ym) == false then yearmark = ""
else
if not not ym:match("(%d+)") then
error("Цифры в обозначении года: " .. ym)
else yearmark = trim(ym) or "года" end
end
return double_couple(jdate, gdate, wd, wm, wy, sq_brts, yearmark)
end
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"3","июня",nil,"21","мая"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"28 августа","","1916 года","15"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"3","июня","1900","21","мая"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"6","июня","1889 год","25","мая"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"28","ноября","1917","15"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"28 августа","nil","1916 года","15"}})
-- =p.Test(mw.getCurrentFrame():newChild{title="smth",args={"4","января","1915","22","декабря","1914 года"}})
-- {{OldStyleDate|день (НС)|месяц (НС)|год (НС)|день (СС)|месяц (СС)|год (СС)}}
function p.Test( frame )
local args = getArgs(frame, { frameOnly = true })
-- необходима проверка и замена nil на " "
--[[mw.log((args[1] or "") .. " " ..
(args[2] or "") .. " " ..
(args[3] or "") .. " " ..
(args[4] or "") .. " " ..
(args[5] or "") .. " " ..
(args[6] or "")) ]]--
local ingdate = triple_txt2date(args[1],args[2],args[3])
local injdate = triple_txt2date(args[4],args[5],args[6])
local j1date, g1date, j2date, g2date = init(4)
mw.log("ingdate-".. (undate(ingdate) or ""))
mw.log("injdate-".. (undate(injdate) or ""))
local bc,wd,wm,wy,sq_brts,ny =
is(args["bc"]),
is(args["wd"]),
is(args["wd"]) and is(args["wm"]),
is(args["wy"]),
is(args["sq_brts"]),
is(args["ny"])
-- подавление формата для локальных тестов
local wd, wm, wy = true, true, true
local yearmark = "года"
local ym = args["yearmark"] or ((mw.ustring.match((args[3] or ""),"(%a+)") or mw.ustring.match((args[6] or ""),"(%a+)")) or "")
-- mw.log("ym " .. ym)
if yesno(ym) then
elseif yesno(ym) == false then yearmark = ""
else
if not not ym:match("(%d+)") then
error("Цифры в обозначении года: " .. ym)
else yearmark = trim(ym) or "года" end
end
if isdate(ingdate) or isdate(injdate) then
if isdate(ingdate) then
j1date, g1date = recalc(ingdate,"g")
ingdate["full"] = true
end
if isdate(injdate) then
j2date, g2date = recalc(injdate,"j")
injdate["full"] = true
end
if ispartdate(ingdate) and ispartdate(injdate) then
mw.log("📏 " .. dmdist(ingdate,injdate))
mw.log("📏 " .. dmdist(j1date,g1date))
mw.log("📏 " .. dmdist(j2date,g2date))
mw.log("📏 " .. dmdist(ingdate,g1date))
mw.log("📏 " .. dmdist(injdate,j2date))
end
end
if ny then
if isyear(j1date) then
else j1date["year"] = "" end
if isyear(j2date) == nil then
else j2date["year"] = "" end
if isyear(g1date) == nil then
else g1date["year"] = "" end
if isyear(g2date) == nil then
else g2date["year"] = "" end
end
if (isdate(j1date) and isdate(g1date) and isdate(j2date) and isdate(g2date)) then
if ((j1date.year == j2date.year)
and (j1date.month == j2date.month)
and (j1date.day == j2date.day)) then
return double_couple(j1date, g1date, wd, wm, wy, sq_brts, yearmark)
else
mw.log("📏 " .. (tostring(dmdist(ingdate,injdate)) or ""))
return glue(args[1],args[2],args[3],args[4],args[5],args[6])
-- категория (предположительная разница в днях) и частичный вывод
end
elseif isdate(j1date) and isdate(g1date) then
return double_couple(j1date, g1date, wd, wm, wy, sq_brts, yearmark) -- категория плюс частичная проверка
elseif isdate(j2date) and isdate(g2date) then
return double_couple(j2date, g2date, wd, wm, wy, sq_brts, yearmark) -- категория плюс частичная проверка
elseif (ispartdate(ingdate) and ispartdate(injdate)) then
mw.log("ingdate ".. (undate(ingdate) or ""))
mw.log("injdate ".. (undate(injdate) or ""))
mw.log("j1date " .. (undate(j1date ) or ""))
mw.log("j2date " .. (undate(j2date ) or ""))
mw.log("g1date " .. (undate(g1date ) or ""))
mw.log("g2date " .. (undate(g2date ) or ""))
mw.log("📏 " .. (tostring(partdist(ingdate,injdate)) or "").. " — " .. (tostring(partdist(injdate,ingdate)) or ""))
return glue(args[1],args[2],args[3],args[4],args[5],args[6])
-- частичный или полный вывод, категория
else
mw.log("ingdate ".. (undate(ingdate) or ""))
mw.log("injdate ".. (undate(injdate) or ""))
mw.log("j1date " .. (undate(j1date ) or ""))
mw.log("j2date " .. (undate(j2date ) or ""))
mw.log("g1date " .. (undate(g1date ) or ""))
mw.log("g2date " .. (undate(g2date ) or ""))
return err .. category.incomplete_parameters
end
end
return p