მოდული:OldStyleDates
ტესტირება რედაქტირება
მოდული სატესტო რეჟიმშია და ის შეიქმნა, როგორც მოდული:Dates-ის ალტერნატიული ვერსია
- {{#invoke:OldStyleDates|parseISO8601|1380-09-08T00:00:00Z}} → -18596908800
- {{#invoke:OldStyleDates|parseISO8601|1700-03-11T00:00:00Z}} → -8514374400
- {{#invoke:OldStyleDates|parseISO8601|1799-06-06T00:00:00Z}} → -5382720000
- {{#invoke:OldStyleDates|parseISO8601|1800-03-12T00:00:00Z}} → -5358614400
- {{#invoke:OldStyleDates|parseISO8601|1825-12-26T00:00:00Z}} → -4544726400
- {{#invoke:OldStyleDates|parseISO8601|1837-02-10T00:00:00Z}} → -4193596800
- {{#invoke:OldStyleDates|parseISO8601|1900-03-13T00:00:00Z}} → -2202854400
- {{#invoke:OldStyleDates|parseISO8601|2900-03-13T00:00:00Z}} → 29354140800
- {{#invoke:OldStyleDates|parseISO8601|1880-01-04T00:00:00Z}} → -2839881600
- {{#invoke:OldStyleDates|formatWiki|-18596908800}} → 8 სექტემბერი 1380
- {{#invoke:OldStyleDates|formatWiki|-8514374400}} → 11 მარტი 1700[ძვ. სტ. 29 თებერვალი]
- {{#invoke:OldStyleDates|formatWiki|-5382720000}} → 6 ივნისი 1799[ძვ. სტ. 26 მაისი]
- {{#invoke:OldStyleDates|formatWiki|-5358614400}} → 12 მარტი 1800[ძვ. სტ. 29 თებერვალი]
- {{#invoke:OldStyleDates|formatWiki|-5358614400}} → 14 (26) დეკემბერი 1825
- {{#invoke:OldStyleDates|formatWiki|-4193596800}} → 10 თებერვალი 1837[ძვ. სტ. 29 იანვარი]
- {{#invoke:OldStyleDates|formatWiki|-2202854400}} → 13 მარტი 1900[ძვ. სტ. 29 თებერვალი]
- {{#invoke:OldStyleDates|formatWiki|-2839881600}} → 23 დეკემბერი 1879 4 იანვარი 1880
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
tail or '',
cat
}--/table.concat внеш.
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
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
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
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
function ternary ( cond , T , F )
if cond then return T else return F end
end
local nominativeMonthes = {'იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი',
'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'}
local genitivusMonthes = {'იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი',
'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'}
function nominativeYear( year )
if ( year >= 0 ) then
return '[[' .. year .. '|' .. year .. ']]'
else
return '[[ძვ. წ. ' .. ( 0 - year ) .. '|ძვ. წ. ' .. ( 0 - year ) .. ']]'
end
end
function inYear( year )
if ( year >= 0 ) then
return '' .. year .. ''
else
return 'ძვ. წ. ' .. ( 0 - year) .. ''
end
end
function p.formatWikiImpl( t1, t2, infocardClass, categoryNamePrefix )
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 );
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 style="white-space:nowrap;">'
if (template == "12") then
datePart = datePart .. string.format( "[[%d %s]]", nd, genitivusMonthes[nm] )
elseif (template == "23") then
datePart = datePart .. string.format( "[[%s]] %s", nominativeMonthes[nm], nominativeYear( ny ) )
elseif (template == "3") then
datePart = datePart .. nominativeYear( ny )
elseif (template == "123") then
datePart = datePart .. string.format( "[[%d %s]] %s", nd, genitivusMonthes[nm], nominativeYear( ny ) )
elseif (template == "124") then
datePart = datePart .. string.format( " [[%d %s|(%d) %s]]", nd, genitivusMonthes[nm], nd, genitivusMonthes[nm] ).. (string.format( "%d", od ))
elseif (template == "1234") then
datePart = datePart .. (string.format( "%d", od )).. string.format( " [[%d %s|(%d) %s]] %s", nd, genitivusMonthes[nm], nd, genitivusMonthes[nm], nominativeYear( ny ) )
elseif (template == "1245") then
datePart = datePart .. string.format(" [[%d %s]]", nd, genitivusMonthes[nm] ).. (string.format( "%d %s", od, genitivusMonthes[om] ))
elseif (template == "12345") then
datePart = datePart .. string.format(" [[%d %s]] %s", nd, genitivusMonthes[nm], nominativeYear( ny ) ) .. (string.format( "<small>[ძვ. სტ. %d %s]</small>", od, genitivusMonthes[om] ))
elseif (template == "123456") then
datePart = datePart .. (string.format( "%d %s %d", od, genitivusMonthes[om], oy )).. '</span> <span style="white-space:nowrap;">'.. string.format(' [[%d %s]] %s', nd, genitivusMonthes[nm], nominativeYear( ny ) )
else
datePart = datePart .. 'მცდარი ფორმატი'
end
datePart = datePart .. '</span>'
local infocardTemplate =
(nd ~= nil and "1" or "") .. (nm ~= nil and "2" or "") .. (ny ~= nil and "3" or "")
return datePart
end
return p