Відмінності між версіями «Модуль:Datetime»

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку
[перевірена версія][перевірена версія]
(перевірка чи виправили)
Рядок 1: Рядок 1:
  +
local getArgs = require('Module:Arguments').getArgs
--[[копії шаблонів для роботи з датами й годинами
 
  +
local p = {}
  +
local bc = ' до н. е.'
   
  +
function p.decadeLink(frame)
todo:
 
  +
-- Allow for invocation via #invoke or directly from another module
mw.text.decode in StrDateToLink
 
  +
local args
]]
 
  +
if frame == mw.getCurrentFrame() then
 
  +
args = frame.args
 
 
local M = {}
 
local floor = math.floor
 
 
table.indexOf = function(t, object)
 
local result
 
if "table" == type( t ) then
 
for i=1,#t do
 
if object == t[i] then
 
result = i
 
break
 
end
 
end
 
end
 
return result
 
end
 
 
now = os.date('*t') --таблиця із поточним часом
 
monthGenetive = {'січня', 'лютого', 'березня', 'квітня', 'травня', 'червня', 'липня', 'серпня', 'вересня',
 
'жовтня', 'листопада', 'грудня'}
 
monthNames = {'січень', 'лютий', 'березень', 'квітень', 'травень', 'червень', 'липень', 'серпень', 'вересень',
 
'жовтень', 'листопад', 'грудень'}
 
 
--внутрішні
 
--юліанський час вказаної григоріанської дати
 
function M.JD(year, month, day, hour, minute, second)
 
hour = hour or 12
 
minute = minute or 0
 
second = second or 0
 
year = year or now.year
 
month = month or now.month
 
day = day or now.day
 
local a = floor((14 - month) / 12)
 
local y = year + 4800 - a
 
local m = month + (12 * a) - 3
 
local aDay = day + floor(((153 * m) + 2) / 5) + (365 * y) + floor(y / 4) - floor(y / 100) + floor(y / 400) - 32045
 
return aDay + (hour - 12)/24 + minute/1440 + second/86400
 
end
 
 
--Чи рік високосний за григоріанським календарем
 
--number
 
function M.LeapGregorian(year)--boolean
 
return ((year % 4) == 0) and
 
(not (((year % 100) == 0) and ((year % 400) ~= 0)))
 
end
 
 
--юліанський день заданої григоріанської дати
 
--{year, month, day}
 
function M.GregorianToJD(date)--number
 
local year, month, day = date.year, date.month, date.day
 
return (1721425.5 - 1) +
 
(365 * (year - 1)) +
 
floor((year - 1) / 4) +
 
(-floor((year - 1) / 100)) +
 
floor((year - 1) / 400) +
 
floor((((367 * month) - 362) / 12) +
 
((month <= 2) and 0 or
 
(M.LeapGregorian(year) and -1 or -2)
 
) +
 
day)
 
end
 
 
--юліанський час заданої юліанської дати
 
--{year, month, day}
 
function M.JulianToJD(date)--number
 
local year, month, day = date.year, date.month, date.day
 
--[[ Adjust negative common era years to the zero-based notation we use. ]]
 
if (year < 1) then
 
year = year + 1;
 
end
 
 
--[[ Algorithm as given in Meeus, Astronomical Algorithms, Chapter 7, page 61 ]]
 
if (month <= 2) then
 
year = year - 1;
 
month = month + 12;
 
end
 
 
return ((floor((365.25 * (year + 4716))) +
 
floor((30.6001 * (month + 1))) +
 
day) - 1524.5);
 
end
 
 
--юліанська дата заданого юліанського часу
 
--number
 
function M.JDtoJulian(td) --{year, month, day}
 
td = td + 0.5
 
local z = floor(td)
 
local a = z
 
local b = a + 1524
 
local c = floor((b - 122.1) / 365.25)
 
local d = floor(365.25 * c)
 
local e = floor((b - d) / 30.6001)
 
 
local month = floor((e < 14) and (e - 1) or (e - 13))
 
local year = floor((month > 2) and (c - 4716) or (c - 4715))
 
local day = b - d - floor(30.6001 * e)
 
 
--[[ If year is less than 1, subtract one to convert from
 
a zero based date system to the common era system in
 
which the year -1 (1 B.C.E) is followed by year 1 (1 C.E.). ]]
 
 
if (year < 1) then
 
year = year - 1
 
end
 
 
return {['year']=year, ['month']=month, ['day']=day}
 
end
 
 
--григоріанська дата заданого юліанського часу
 
--number
 
function M.JDtoGregorian(jd)--{year, month, day}
 
local wjd = floor(jd - 0.5) + 0.5
 
local depoch = wjd - 1721425.5
 
local quadricent = floor(depoch / 146097)
 
local dqc = depoch % 146097
 
local cent = floor(dqc / 36524)
 
local dcent = dqc % 36524
 
local quad = floor(dcent / 1461)
 
local dquad = dcent % 1461
 
local yindex = floor(dquad / 365)
 
local year = (quadricent * 400) + (cent * 100) + (quad * 4) + yindex
 
if (not((cent == 4) or (yindex == 4))) then
 
year = year + 1
 
end
 
local yearday = wjd - M.GregorianToJD({['year']=year, month=1, day=1})
 
local leapadj = ((wjd < M.GregorianToJD({['year']=year, month=3, day=1})) and 0 or
 
(M.LeapGregorian(year) and 1 or 2)
 
)
 
local month = floor((((yearday + leapadj) * 12) + 373) / 367)
 
local day = (wjd - M.GregorianToJD({['year']=year, ['month']=month, day=1})) + 1
 
 
return {['year']=year, ['month']=month, ['day']=day}
 
end
 
 
--юліанська дата в григоріанську
 
function M.JulianToGregorian(date)--{year, month, day}
 
return M.JDtoGregorian(M.JulianToJD(date))
 
end
 
 
--григоріанська дата в юліанську
 
function M.GregorianToJulian(date)--{year, month, day}
 
return M.JDtoJulian(M.GregorianToJD(date))
 
end
 
 
-- номер дня з початку літочислення за григоріанським календарем
 
--{day, month, year}
 
function M.GregorianSerial(date) --number
 
local year = date.year
 
local month = date.month
 
local day = date.day
 
return ((year - 1) * 365)
 
+ (((year - 1) - ((year - 1) % 4)) / 4) --add a day for every leap
 
- (((year - 1) - ((year - 1) % 100)) / 100) --subtract 100 year exception
 
+ (((year - 1) - ((year - 1) % 400)) / 400) --readd 400 year exception
 
 
--Days so far this year:
 
 
+ (--add days for past months this year--> <!--Gives 1 or 2 extra days because of February-->
 
((month - 1) < 8)
 
and floor((month - 1) * 30.5)
 
or floor((month - 1) * 30.5 + 0.9)
 
)
 
- ((month <= 2) and 0 or
 
( -- if leap year -->
 
((year / 4) == floor(year / 4) --If divisible by 4-->
 
and (year / 100 ~= floor(year / 100))
 
) --and not by 100-->
 
and 1 or 2
 
)
 
)
 
+ ((month <= 2) and 0 or
 
( --400 year exception-->
 
((year / 400) == floor(year / 400))
 
and 1 or 0
 
)
 
)
 
+ day
 
end
 
 
--{day1, month1, year1, day2, month2, year2}
 
function M.DaysBetween(dates) --number
 
return GregorianSerialDate({day = dates.day1, month = dates.month1, year = dates.year1})
 
- GregorianSerialDate({day = dates.day2, month = dates.month2, year = dates.year2})
 
end
 
 
--number
 
function M.CenturyLocativeCase(century) --string
 
if century < 1 then
 
return -(date.century - 1)..' столітті до н. е.'
 
else
 
return century..' столітті'
 
end
 
end
 
 
--string або number
 
function M.MonthGenetiveCase(month) --string
 
if type(month) == 'string' then
 
month = table.indexOf(monthNames, mw.ustring.lower(month));
 
 
else
 
else
if type(month) ~= 'number' then
+
args = frame
error('Незрозумілий місяць')
 
end
 
 
end
 
end
assert((month <= 12) and (month >= 1), 'Недопустимий номер місяця - ' .. month)
 
return monthGenetive[month]
 
end
 
   
  +
return p._decadeLink(args[1], args[2])
--string
 
function M.MonthToNum(month) --number
 
local num = table.indexOf(monthNames, mw.ustring.lower(month));
 
if not num then
 
num = table.indexOf(monthGenetive, mw.ustring.lower(month));
 
end
 
if num then
 
return num
 
else
 
error('Незрозумілий місяць - ' .. month)
 
end
 
 
end
 
end
   
  +
function p._decadeLink(decade, stripBc)
--string
 
  +
if decade == 0 then
function M.YearToNum(year) --number
 
  +
return '[[0-ві]]'
local err = 'Незрозумілий рік - ' .. year
 
  +
elseif decade > 0 then
local match, _, year, tail = year:find'^(%d+)(.*)'
 
  +
if decade == ((decade-(decade % 100))/100)*100 then
assert(match, err)
 
  +
return '[[' .. decade .. '0-ні]]'
year = tonumber(year)
 
  +
elseif (decade-4)/10 == ((decade-(decade % 10))/10) then
if tail ~= '' then
 
  +
return '[[' .. decade .. '0-ві]]'
local match, _ = string.find(tail, '^%s*до%s+н%s*%.%s*е%s*%.%s*$')
 
  +
else
if match then
 
  +
return '[[' .. decade .. '0-ті]]'
year = -year + 1
 
  +
end
  +
else
  +
local decadeBc = -1 - decade
  +
if decadeBc == 0 then
  +
return decadeBcLink('0-ві', stripBc)
  +
elseif decade == ((decadeBc - (decadeBc % 100))/100)*100 then
  +
return decadeBcLink(decadeBc .. '0-ні', stripBc)
  +
elseif (decadeBc-4)/10 == ((decadeBc-(decadeBc % 10))/10) then
  +
return decadeBcLink(decadeBc .. '0-ві', stripBc)
 
else
 
else
error(err)
+
return decadeBcLink(decadeBc .. '0-ті', stripBc)
end
+
end
 
end
 
end
return year
 
 
end
 
end
   
  +
function decadeBcLink(link, stripBc)
--{day, month, year}, boolean
 
  +
local result = '[[' .. link .. bc
function M.DateToLink(date, isJulian) --string
 
if isJulian then
+
if stripBc then
  +
result = result .. '|' .. link .. ']]'
local greg = M.JulianToGregorian(date)
 
  +
else
if date.year ~= greg.year then
 
  +
result = result .. ']]'
if date.year < 1 then
 
date.year = -(date.year - 1) .. ' до н. е.'
 
end
 
if greg.year < 1 then
 
greg.year = -(greg.year - 1) .. ' до н. е.'
 
end
 
return '[['..date.day..' '..M.MonthGenetiveCase(date.month)..']] [['..date.year..']] ([['..greg.day..' '..M.MonthGenetiveCase(greg.month)..']] [['..greg.year..']])'
 
else
 
if greg.year < 1 then
 
greg.year = -(greg.year - 1) .. ' до н. е.'
 
end
 
return '[['..date.day..' '..M.MonthGenetiveCase(date.month)..']] ([['..greg.day..' '..M.MonthGenetiveCase(greg.month)..']]) [[' .. greg.year .. ']]'
 
end
 
else
 
if date.year < 1 then
 
date.year = -(date.year - 1) .. ' до н. е.'
 
end
 
return '[[' .. date.day .. ' ' .. M.MonthGenetiveCase(date.month) .. ']] [[' .. date.year .. ']]'
 
 
end
 
end
  +
return result
 
end
 
end
   
  +
return p
function M.printDayMonth(day, month, frmt)
 
if frmt == 'текст' then
 
return day..' '..M.MonthGenetiveCase(month)
 
elseif frmt == 'цифровий' then
 
return day..'.'..month
 
elseif frmt == 'посилання' then
 
return '[['..day..' '..M.MonthGenetiveCase(month)..']]'
 
end
 
end
 
 
function M.printCentury(century, frmt)
 
local function CenturyToStr(century)
 
if century < 1 then
 
return -(date.century - 1)..' століття до н. е.'
 
else
 
return century..' століття'
 
end
 
end
 
 
if frmt == 'текст' then
 
return CenturyToStr(century)
 
elseif frmt == 'цифровий' then
 
return century
 
elseif frmt == 'посилання' then
 
return '[['..CenturyToStr(century)..']]'
 
else
 
error('Запитано незрозумілий формат')
 
end
 
end
 
 
function M.printYear(year, frmt)
 
local function YearToStr(year)
 
if year < 1 then
 
return -(date.year - 1) .. ' до н. е.'
 
else
 
return year
 
end
 
end
 
 
if frmt == 'текст' then
 
return YearToStr(year)
 
elseif frmt == 'цифровий' then
 
return year
 
elseif frmt == 'посилання' then
 
return '[['..YearToStr(year)..']]'
 
end
 
end
 
 
function M.TimeToString(date, frmt, forceJulian)
 
if not date then
 
error('Не вказано час')
 
end
 
if date.day then
 
return M.GregDateToString(date, frmt, forceJulian)
 
elseif date.century then
 
return M.printCentury(date.century, frmt)
 
else
 
error('Незрозумілий час')
 
end
 
end
 
 
function M.GregDateToString(date, frmt, forceJulian)
 
--todo: check frmt
 
if forceJulian then
 
local jul = M.GregorianToJulian(date)
 
if date.year ~= jul.year then
 
if (frmt == 'текст') or (frmt == 'посилання') then
 
return
 
M.printDayMonth(jul.day, jul.month, frmt)..' '..M.printYear(jul.year, frmt)
 
..' ('..M.printDayMonth(date.day, date.month, frmt)..' '..M.printYear(date.year, frmt)..')'
 
elseif frmt == 'цифровий' then
 
return
 
M.printDayMonth(jul.day, jul.month, frmt)..'.'..M.printYear(jul.year, frmt)
 
..'.('..M.printDayMonth(date.day, date.month, frmt)..'.'..M.printYear(date.year, frmt)..')'
 
end
 
else
 
if (frmt == 'текст') or (frmt == 'посилання') then
 
return
 
M.printDayMonth(jul.day, jul.month, frmt)
 
..' ('..M.printDayMonth(date.day, date.month, frmt)..') '..M.printYear(date.year, frmt)
 
elseif frmt == 'цифровий' then
 
return
 
M.printDayMonth(jul.day, jul.month, frmt)..'.'..M.printYear(jul.year, frmt)
 
..'.('..M.printDayMonth(date.day, date.month, frmt)..')'
 
end
 
end
 
else
 
if (frmt == 'текст') or (frmt == 'посилання') then
 
return
 
M.printDayMonth(date.day, date.month, frmt)..' '..M.printYear(date.year, frmt)
 
elseif frmt == 'цифровий' then
 
return
 
M.printDayMonth(date.day, date.month, frmt)..'.'..M.printYear(date.year, frmt)
 
end
 
end
 
end
 
 
--[[string (дата), string (необов'язковий модифікатор, який
 
обмежує допустимі формати: 'ц' - цифровий, 'з' - звичайний)]]
 
function M.StringToDate(s, allowedFormat) --{day, month, year}
 
local day, month, year
 
local allowNumeric, allowPlain = true, true
 
if allowedFormat then
 
allowNumeric = mw.ustring.find(allowedFormat, 'ц')
 
allowPlain = mw.ustring.find(allowedFormat, 'з')
 
end
 
if allowNumeric then
 
local found, _, d, m, y = string.find(s, '^%s*(%d+)%s*%.%s*(%d+)%s*%.%s*(%-?%d+)')
 
if found then
 
return {day = tonumber(d), month = tonumber(m), year = tonumber(y)}
 
end
 
end
 
if allowPlain then
 
local found, _, d, m, y = mw.ustring.find(s, '^%s*(%d+)%s+(%a+)%s+(%d+.*)')
 
if found then
 
return {day = tonumber(d), month = M.MonthToNum(m), year = M.YearToNum(y)}
 
end
 
end
 
return nil
 
end
 
 
return M
 

Версія за 22:06, 6 липня 2020

local getArgs = require('Module:Arguments').getArgs
local p = {}
local bc = ' до н. е.'

function p.decadeLink(frame)
    -- Allow for invocation via #invoke or directly from another module
    local args
    if frame == mw.getCurrentFrame() then
        args = frame.args
    else
        args = frame
    end

    return p._decadeLink(args[1], args[2])
end

function p._decadeLink(decade, stripBc)
	if decade == 0 then
		return '[[0-ві]]'
	elseif decade > 0 then
		if decade == ((decade-(decade % 100))/100)*100 then
			return '[[' .. decade .. '0-ні]]'
		elseif (decade-4)/10 == ((decade-(decade % 10))/10) then
    		return '[[' .. decade .. '0-ві]]'
    	else
    		return '[[' .. decade .. '0-ті]]'
    	end	
    else 
    	local decadeBc = -1 - decade
    	if decadeBc == 0 then
    		return decadeBcLink('0-ві', stripBc)
    	elseif decade == ((decadeBc - (decadeBc % 100))/100)*100 then
    		return decadeBcLink(decadeBc .. '0-ні', stripBc)
    	elseif (decadeBc-4)/10 == ((decadeBc-(decadeBc % 10))/10) then
        	return decadeBcLink(decadeBc .. '0-ві', stripBc)
        else
        	return decadeBcLink(decadeBc .. '0-ті', stripBc)
        end
    end
end

function decadeBcLink(link, stripBc)
	local result = '[[' .. link .. bc 
	if stripBc then
    	result = result .. '|' .. link .. ']]'
    else
    	result = result .. ']]'
	end
	return result
end

return p