Изменения

первое приближение для Шаблон:Ambox/тесты#Тесты_дат
Строка 57: Строка 57:  
"SAST","SBT","SCT","SLT","SST","SST","TAHT","THA","UTC","UYST","UYT","VET",
 
"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"}
 
"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%d)[-%.%s/\\](%d%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"] = {2,3} }, -- yyyy mm
 +
{"(%d+)%s(%l+)%s(%d%d%d%d)", ["order"] = {1,2,3} }, -- d mmm y
 +
{"(%l+)%s(%d%d%d%d)", ["order"] = {1,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 lang = {"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 (lang, month_lang)
 +
for i=1, #lang do
 +
reverse_month_lang[lang[i]] = reverse_table(month_lang[lang[i]])
 +
end
 +
end
    
-- 10) Блок общих функций
 
-- 10) Блок общих функций
Строка 139: Строка 187:  
then return false
 
then return false
 
else return true
 
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
 
end
 
end
Строка 217: Строка 276:  
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, #lang do
 +
    if inlist(mw.ustring.lower(str),month_lang[lang[i]]) then
 +
return reverse_month_lang[lang[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(date_string,pattern[i][1])
 +
if (result_1 or "") > "" then
 +
out_date_str[pattern[i].order[1]],
 +
    out_date_str[pattern[i].order[2]],
 +
    out_date_str[pattern[i].order[3]] =
 +
    result_1, result_2, result_3
 +
    break
 +
end
 +
end
 +
if not out_date_str[1] then
 +
out_date_str[1] = 1
 +
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 numstr2date = function(numstr)
Строка 552: Строка 652:  
end
 
end
   −
function p.ToIso( frame ) -- возможно неиспользуемая
+
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12 декабря 2020"}})
 +
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"декабрь 2020"}}) -- не работает
 +
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"12-2020"}}) -- не работает
 +
-- =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.11"}}) -- не работает
 +
-- =p.ToIso(mw.getCurrentFrame():newChild{title="smth",args={"11.2021"}}) -- не работает
 +
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(lang, month_lang)
 
     -- парсинг входящей даты по шаблону
 
     -- парсинг входящей даты по шаблону
     local pattern = "(%d+)%.(%d+)%.(%d+)"
+
     local date = parse_date(datein)
    local dayin, monthin, yearin = datein:match(pattern)
+
     if not (type(date.year) == 'number') then  
    local year = tonumber(yearin)
  −
    local month = tonumber(monthin)
  −
    local day = tonumber(dayin)
  −
    -- проверка параметров
  −
     if not (type(year) == 'number') then  
   
         return error("Wrong year")
 
         return error("Wrong year")
 
     end
 
     end
     if not (1 <= month and month <= 12) then  
+
     if not (1 <= date.month and date.month <= 12) then  
 
         return error("Wrong month")
 
         return error("Wrong month")
 
     end
 
     end
     if not (1 <= day and day <= 31) then  
+
     if not (1 <= date.day and date.day <= month_end_day(date.month,date.year)) then  
 
         return error("Wrong day")
 
         return error("Wrong day")
 
     end
 
     end
     local timedate = os.time{year=year, month=month, day=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
Анонимный участник