Перейти к содержанию
Главное меню
Главное меню
переместить в боковую панель
скрыть
Навигация
Заглавная страница
Указатели
Свежие правки
Случайная страница
Справка по MediaWiki
Народные Сказки
Поиск
Найти
Создать учётную запись
Войти
Персональные инструменты
Создать учётную запись
Войти
Страницы для неавторизованных редакторов
узнать больше
Вклад
Обсуждение
Редактирование:
Модуль:Dates
Модуль
Обсуждение
English
Читать
Править код
История
Инструменты
Инструменты
переместить в боковую панель
скрыть
Действия
Читать
Править код
История
Общие
Ссылки сюда
Связанные правки
Служебные страницы
Сведения о странице
Внимание:
Вы не вошли в систему. Ваш IP-адрес будет общедоступен, если вы запишете какие-либо изменения. Если вы
войдёте
или
создадите учётную запись
, её имя будет использоваться вместо IP-адреса, наряду с другими преимуществами.
Анти-спам проверка.
Не
заполняйте это!
--[[ В этом модуле собраны функции, связанные с работой с датами. ]] local monthg = {'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', "сентября", "октября", "ноября", "декабря"} local monthd = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} local function DecodeDate(d)-- Ч, М, Г, СЧ, СМ, СГ, хвост --дата: "%-?%d+"=год, "%d+%.%d+"=число месяца, "%d+%.%d+%.%-?%d+"=ЧМГ, -- потом в скобках м.б. переопределено для старого стиля начиная с числа local nd=d:match("^[%d.-]*"); local od=d:match("^[%d.-]*%s*%(%s*([%d.-]*)%s*%)"); local tail = d:match("^[%d.-]+%s*%(%s*[%d.-]+%s*%)%s*(%S.*)") or d:match("^[%d.-]+%s*([^%s%d].*)"); if nd:match('^%-?%d+$' ) then return nil, nil, tonumber(nd), nil, nil, od and tonumber(od:match("%-?%d+$")),tail else local j,m,y=nd:match("^(%d+)%.(%d+)%.?(%-?%d*)"); if j then if od then local oj, om, oy = od:match("^(%d+)%.?(%d*)%.?(%-?%d*)"); return j and tonumber(j), m and tonumber(m), y>'' and tonumber(y) or nil, oj and tonumber(oj), om>'' and tonumber(om) or nil, oy>'' and tonumber(oy) or nil, tail end return j and tonumber(j), m and tonumber(m), y>'' and tonumber(y) or nil, nil, nil, nil, tail else return nil end end end local function Diffy(d1,m1,y1,d0,m0,y0)--аналог Персона/Дата/Прошло лет return y1-y0 - ( y1*y0<=0 and 1 or 0 ) - ( (m1<m0 or m1==m0 and d1<d0) and 1 or 0 ) end local function Year0(y,t)-- аналог Год0 if y>0 then return table.concat{ '[[', tostring(y), ' год|', t and tostring(y)..' '..t or tostring(y), ']]' } else return table.concat{ '[[', tostring(-y), ' год до н. э.|', t and tostring(-y)..' '..t or tostring(-y), ' до н. э.]]' } end end local function FormDate(j,m,y,oj,om,oy,mo)-- ~ Персона/Дата/Logic 4 if j then if not m then return "''формат неверен''" end if y then return string.format( '<span class="nowrap">%s<span style="display:none">(<span class="%s">%04i-%02i-%02i</span>)</span></span>', table.concat( oj and ( om and ( oy and {-- ДД ММММ ГГГГ ([[ДД ММММ]] [[ГГГГ]]) oj,' ',monthg[om],' ',oy, '</span> <span class="nowrap">([[', j, ' ', monthg[m],']] ',Year0(y),')' } or {-- ДД ММММ ([[ДД ММММ]]) [[ГГГГ]] oj,' ',monthg[om],' ([[',j,' ',monthg[m],']]) ',Year0(y) } ) or {-- ДД [[ДД ММММ|(ДД) ММММ]] [[ГГГГ]] oj,' [[',j,' ',monthg[m],'|','(',j,') ',monthg[m],']] ',Year0(y) } ) or {'[[',j,' ',monthg[m],']] ',Year0(y)} ),--/table.concat ({['Рождения']='bday',['Смерти']='dday'})[mo] or '', y,m,j )--/string.format else return '<span class="nowrap">' .. table.concat( oj and ( om and {-- ДД ММММ ([[ДД ММММ]]) oj,' ',monthg[om],' ([[',j,' ',monthg[m],']])</span>' } or {-- ДД [[ДД ММММ|(ДД) ММММ]] oj,' [[',j,' ',monthg[m],'|','(',j,') ',monthg[m],']]</span>' } ) or {'[[',j,' ',monthg[m],']]</span>'} ) end else return y and string.format( '<span class="nowrap">%s<span style="display:none;">(<span class="bday">%04i</span>)</span></span>', Year0(y,'год'),y) or "''формат неверен''" end end local function GetDate(D)--dd.mm.-?yyyy или -?yyyy-mm-dd в три переменных d,m,y local d,m,y = d:match('^%s*(%d%d?)[/.]([01]?%d)[/.](%-?%d+)') if not d then y,m,d = D:match('^%s*(%-?%d+)[-\\]0*(1?%d)[-\\]0*(%d+)') end return tonumber(d),tonumber(m),tonumber(y) end local function Cmp(a,b)--Сравнивает две даты, результат соответственно -1, 0 или 1 local d1,m1,y1 = GetDate(a) local d2,m2,y2 = GetDate(b) return d1 and d2 and (--nil, если формат не опознан y1==y2 and ( m1==m2 and ( d1==d2 and 0 or d1<d2 and -1 or 1 ) or m1<m2 and -1 or 1 ) or y1<y2 and -1 or 1 ) end local function Yyyymmdd(r)--Переводит русскую дату в YYYY,MM,DD local d, m, y, M = mw.ustring.match(r, "^%s*(%d%d?)%s+([а-яА-Я]+)%s+(%d+)") if not m then return nil end m = mw.ustring.lower(m) --тупо перебор for i = 1, 12 do if m == monthg[i] then M = i break end end if not M then return nil end return tonumber(y), M, tonumber(d) end local p = {} p = { ifdate=function(f)-- Для шаблона "Если дата", имитирует старое поведение -- Аргументы передаются шаблону return f:getParent().args[ mw.ustring.match(frame.args[1],"^[ %d.%-−%()]*$") and 2 or 3 ] end; DecodeDate = DecodeDate; Diffy = Diffy; Year0 = Year0; GetDate = GetDate; Cmp = Cmp; Yyyymmdd = Yyyymmdd; diffy = function(f)-- принимает параметры #invoke в виде двух строк-дат local d1,m1,y1=DecodeDate(f.args[1]); local d0,m0,y0=DecodeDate(f.args[2]) return Diffy(d1,m1,y1,d0,m0,y0) end; monthg=function(f) return monthg[ f.args[1] or f:getParent().args[1] ] end;--realmonth persdate=function(f)-- Для шаблона Персона/Дата;{{#invoke:dates|persdate|nocat={{NAMESPACE}}}} local frame=f:getParent(); local catpref,mo,d,d2={['Рождения']='Родившиеся',['Смерти']='Умершие'}, frame.args[1],frame.args[2],frame.args[3] local cat, j,m,y,oj,om,oy,tail, j2,m2,y2, age = '' if d then j,m,y,oj,om,oy,tail=DecodeDate(d:gsub('−','-')); if not (j or y) then return (frame.args.nocat and d or d..'[[Category:Википедия:Статьи с ручной викификацией дат в карточке]]') end end; if d2 then j2,m2,y2 = DecodeDate(d2:gsub('−','-')); end; return table.concat{ FormDate(j,m,y,oj,om,oy,mo), ( (frame.args['nopersoncat'] or '')~='' or (f.args['nocat'] or '')~='' ) and '' or table.concat{ '[[Category:Персоналии по алфавиту]]', j and string.format('[[Category:%s %i %s]]',catpref[mo],j,monthg[m]) or '', y and string.format('[[Category:%s в %s]]',catpref[mo],y,Year0(y,'году')) or '' },--/table.concat внутр. (function(F)--возраст if not F then return '' end; local n=F(); return n and string.format(" (%i %s)%s", n, mw.getLanguage('ru'):plural(n,'год','года','лет'), n>150 and '[[Category:Википедия:Статьи о персоналиях с большим текущим возрастом]]' or '' ) or '' end)( ({ ['Рождения']=function() local now=os.date('*t'); if (not d2 or d2=='') and j and m and y then return Diffy(now.day,now.month,now.year,j,m,y) end end, ['Смерти']=function() return j and m and y and j2 and m2 and y2 and Diffy(j,m,y,j2,m2,y2); end, })[mo] ),--конец вызова функции возраста tail or '', cat }--/table.concat внеш. end; formdate=function(f) -- Формирует дату по 3--6 параметрам #invoke или шаблона --не использовать с пустыми аргументами if (f.args[1] or '')~='' and (f.args[2] or '')~='' or (f.args[3] or '')~='' then return FormDate(f.args[1],f.args[2],f.args[3],f.args[4],f.args[5],f.args[6],f.args['m']) else local tf=f:getParent(); return FormDate(tf.args[1],tf.args[2],tf.args[3],tf.args[4],tf.args[5],tf.args[6],tf.args['m']) end end; cmp=function(f)--Сравнивает две даты, результат соответственно -1, 0 или 1 return Cmp(f.args[1],f.args[2]) end; G2J=function(f)--перевод григорианских дат в юлианские, возврат DD.MM.YYYY --Не знает про 15 октября 1582 года, не работает до нашей эры и после ???99 года --Если есть второй аргумент, преобразует только ДО этой даты включительно --Если есть третий аргумент, результат форматирует под Персона/Дата local d,m,y=GetDate(f.args[1]) if f.args[2] and Cmp(f.args[1],f.args[2])==1 then return string.format("%i.%i.%i",d,m,y) end local shift=math.floor(y/100)-math.floor(y/400)-2 if d-shift>0 then return f.args[3] and string.format("%i.%i.%i (%i)",d,m,y,d-shift) or string.format("%i.%i.%i",d-shift,m,y) else if m==1 then return f.args[3] and string.format("%i.1.%i (%i.12.%i)",d,y,31+d-shift,y-1) or string.format("%i.12.%i",31+d-shift,y-1) elseif m==3 then return f.args[3] and string.format("%i.3.%i (%i.2)", d,y, (y%4==0 and 29 or 28)+d-shift-(y%100==0 and y%400~=0 and 1 or 0) ) or string.format("%i.2.%i", (y%4==0 and 29 or 28)+d-shift-(y%100==0 and y%400~=0 and 1 or 0) ,y) else return f.args[3] and string.format( "%i.%i.%i (%i.%i)", d,m,y, monthd[m-1]+d-shift,m-1 ) or string.format("%i.%i.%i",monthd[m-1]+d-shift,m-1,y) end end end; -- Переводит русскую дату в YYYY-MM-DD. Возвращает входное значение, если дата уже в этом формате yyyymmdd = function(f) local date, hourmin = f.args[1] if mw.ustring.match(date, "^%s*%d+\-%d+\-%d+") then return date end hourmin = mw.ustring.match(date, "%s+%d+:%d+$") local y, m, d = Yyyymmdd(date) if not y then return '<span class="error">Ошибка: некорректный формат даты.</span>' end return string.format('%4i-%02i-%02i', y, m, d) .. (hourmin or '') end } function table.val_to_str ( v ) if "string" == type( v ) then v = string.gsub( v, "\n", "\\n" ) if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then return "'" .. v .. "'" end return '"' .. string.gsub(v,'"', '\\"' ) .. '"' else return "table" == type( v ) and table.tostring( v ) or tostring( v ) end end function table.key_to_str ( k ) if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then return k else return "[" .. table.val_to_str( k ) .. "]" end end function table.tostring( tbl ) local result, done = {}, {} for k, v in ipairs( tbl ) do table.insert( result, table.val_to_str( v ) ) done[ k ] = true end for k, v in pairs( tbl ) do if not done[ k ] then table.insert( result, table.key_to_str( k ) .. "=" .. table.val_to_str( v ) ) end end return "{" .. table.concat( result, "," ) .. "}" end local function parseISO8601Date(str) local pattern = "(%-?%d+)%-(%d+)%-(%d+)T" local Y, M, D = mw.ustring.match( str, pattern ) return tonumber(Y), tonumber(M), tonumber(D) end local function parseISO8601Time(str) local pattern = "T(%d+):(%d+):(%d+)%Z" local H, M, S = mw.ustring.match( str, pattern) return tonumber(H), tonumber(M), tonumber(S) end local function parseISO8601Offset(str) if str:sub(-1)=="Z" then return 0,0 end -- ends with Z, Zulu time -- matches ±hh:mm, ±hhmm or ±hh; else returns nils local pattern = "([-+])(%d%d):?(%d?%d?)$" local sign, oh, om = mw.ustring.match( str, pattern) sign, oh, om = sign or "+", oh or "00", om or "00" return tonumber(sign .. oh), tonumber(sign .. om) end function p.parseISO8601(str) if 'table'==type(str) then if str.args and str.args[1] then str = '' .. str.args[1] else return 'unknown argument type: ' .. type( str ) .. ': ' .. table.tostring( str ) end end local Y,M,D = parseISO8601Date(str) local h,m,s = parseISO8601Time(str) local oh,om = parseISO8601Offset(str) return tonumber(os.time({year=Y, month=M, day=D, hour=(h+oh), min=(m+om), sec=s})) end local g2uBoundary1 = p.parseISO8601('1582-10-15T00:00:00Z') local g2uBoundary2 = p.parseISO8601('1700-03-12T00:00:00Z') local g2uBoundary3 = p.parseISO8601('1800-03-13T00:00:00Z') local g2uBoundary4 = p.parseISO8601('1900-03-14T00:00:00Z') local g2uBoundary5 = p.parseISO8601('1918-01-26T00:00:00Z') -- декрет Ленина -- Передаваемое время обязано быть по Григорианскому календарю (новому стилю) function p.formatWiki( time, infocardClass, categoryNamePrefix ) if 'table'==type( time ) then if time.args and time.args[1] then time = tonumber( time.args[1] ) else return 'unknown argument type: ' .. type( time ) .. ': ' .. table.tostring( time ) end end local t = os.date("*t", time) if time < g2uBoundary1 then -- выводим просто юлианский календарь. Задавать тут григорианский некорректно return p.formatWikiImpl( t, t, infocardClass, categoryNamePrefix ) end -- Специальные даты if t.year == 1700 and t.month == 3 and t.day == 11 then return p.formatWikiImpl( {year=1700, month=2, day=29}, t, infocardClass, categoryNamePrefix) end if t.year == 1800 and t.month == 3 and t.day == 12 then return p.formatWikiImpl( {year=1800, month=2, day=29}, t, infocardClass, categoryNamePrefix ) end if t.year == 1900 and t.month == 3 and t.day == 13 then return p.formatWikiImpl( {year=1900, month=2, day=29}, t, infocardClass, categoryNamePrefix ) end if g2uBoundary1 <= time and time < g2uBoundary2 then return p.formatWikiImpl( os.date("*t", time - 10 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix ) end if g2uBoundary2 <= time and time < g2uBoundary3 then return p.formatWikiImpl( os.date("*t", time - 11 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix ) end if g2uBoundary3 <= time and time < g2uBoundary4 then return p.formatWikiImpl( os.date("*t", time - 12 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix ) end if g2uBoundary4 <= time and time < g2uBoundary5 then return p.formatWikiImpl( os.date("*t", time - 13 * 24 * 60 * 60), t, infocardClass, categoryNamePrefix ) end --только Григорианский календарь return p.formatWikiImpl( t, t, infocardClass, categoryNamePrefix ) end local function ternary ( cond , T , F ) if cond then return T else return F end end local nominativeMonthes = {'январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'} local genitivusMonthes = {'января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'} local function nominativeYear( year, nolinks ) if ( year >= 0 ) then return nolinks and year or '[[' .. year .. ' год|' .. year .. ']]' else return nolinks and ( 0 - year ) .. ' до н. э.' or '[[' .. ( 0 - year ) .. ' год до н. э.|' .. ( 0 - year ) .. ' до н. э.]]' end end local function inYear( year ) if ( year >= 0 ) then return '' .. year .. ' году' else return '' .. ( 0 - year) .. ' году до н. э.' end end function p.formatWikiImpl( t1, t2, infocardClass, categoryNamePrefix, leftBracket, rightBracket, nolinks ) local nd = t2.day; local nm = t2.month; local ny = t2.year; local od = ternary ( t1.day ~= t2.day , t1.day, nil ); local om = ternary ( t1.month ~= t2.month , t1.month, nil ); local oy = ternary ( t1.year ~= t2.year , t1.year, nil ); if leftBracket == nil then leftBracket = '(' end if rightBracket == nil then rightBracket = ')' end local JulianComment = function(s) return tostring(mw.html.create("abbr") :attr("title","по юлианскому календарю") :wikitext(s) :done()) end local template = (nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "") .. (od ~= nil and "4" or "") .. (om ~= nil and "5" or "") .. (oy ~= nil and "6" or "") local datePart = '<span class="nowrap">' if (template == "12") then datePart = datePart .. string.format( nolinks and "%d %s" or "[[%d %s]]", nd, genitivusMonthes[nm] ) elseif (template == "23") then datePart = datePart .. string.format( "%s %s", nominativeMonthes[nm], nominativeYear( ny, nolinks ) ) elseif (template == "3") then datePart = datePart .. nominativeYear( ny, nolinks ) elseif (template == "123") then datePart = datePart .. string.format( nolinks and "%d %s %s" or "[[%d %s]] %s", nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) ) elseif (template == "124") then if nolinks then datePart = datePart .. JulianComment(string.format( "%d", od ) ).. string.format( " " .. leftBracket .. "%d" .. rightBracket .. " %s", nd, genitivusMonthes[nm] ) else datePart = datePart .. JulianComment(string.format( "%d", od ) ).. string.format( " [[%d %s|" .. leftBracket .. "%d" .. rightBracket .. " %s]]", nd, genitivusMonthes[nm], nd, genitivusMonthes[nm] ) end elseif (template == "1234") then if nolinks then datePart = datePart .. JulianComment(string.format( "%d", od ) ).. string.format( " |" .. leftBracket .. "%d" .. rightBracket .. " %s %s", nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) ) else datePart = datePart .. JulianComment(string.format( "%d", od ) ).. string.format( " [[%d %s|" .. leftBracket .. "%d" .. rightBracket .. " %s]] %s", nd, genitivusMonthes[nm], nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) ) end elseif (template == "1245") then datePart = datePart .. JulianComment(string.format( "%d %s", od, genitivusMonthes[om] ) ).. string.format(" " .. leftBracket .. (nolinks and "%d %s" or "[[%d %s]]") .. rightBracket .. "", nd, genitivusMonthes[nm] ) elseif (template == "12345") then datePart = datePart .. JulianComment(string.format( "%d %s", od, genitivusMonthes[om] ) ).. string.format(" " .. leftBracket .. (nolinks and "%d %s" or "[[%d %s]]") .. rightBracket .. " %s", nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) ) elseif (template == "123456") then datePart = datePart .. JulianComment(string.format( "%d %s %d", od, genitivusMonthes[om], oy )) .. '</span> <span class="nowrap">' .. string.format(" " .. leftBracket .. (nolinks and "%d %s %s" or "[[%d %s]] %s") .. rightBracket , nd, genitivusMonthes[nm], nominativeYear( ny, nolinks ) ) else datePart = datePart .. 'формат неверен' end datePart = datePart .. '</span>' local infocardTemplate = (nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "") if infocardClass then if (infocardTemplate == "123") then datePart = datePart .. string.format('<span style="display:none">(<span class="%s">%04d-%02d-%02d</span>)</span>', infocardClass , ny , nm , nd ) elseif (infocardTemplate == "23") then datePart = datePart .. string.format('<span style="display:none">(<span class="%s">%04d-%02d</span>)</span>', infocardClass , ny , nm ) elseif (infocardTemplate == "3") then datePart = datePart .. string.format('<span style="display:none;">(<span class="%s">%04d</span>)</span>', infocardClass , ny ) end end if categoryNamePrefix then if ( nd ~= nil and nm ~= nil) then datePart = datePart .. '[[Category:' .. categoryNamePrefix .. ' ' .. nd .. ' ' .. genitivusMonthes[nm] .. ']]' end if ( ny ~= nil) then datePart = datePart .. '[[Category:' .. categoryNamePrefix .. ' в ' .. inYear( ny ) .. ']]' end end return datePart end return p
Описание изменений:
Пожалуйста, учтите, что любой ваш вклад в проект «Народные Сказки» может быть отредактирован или удалён другими участниками. Если вы не хотите, чтобы кто-либо изменял ваши тексты, не помещайте их сюда.
Вы также подтверждаете, что являетесь автором вносимых дополнений, или скопировали их из источника, допускающего свободное распространение и изменение своего содержимого (см.
РуСказки:Авторские права
).
НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ МАТЕРИАЛЫ!
Отменить
Справка по редактированию
(в новом окне)
Отобразить/Скрыть ограниченную ширину содержимого