Documentation for this module may be created at Module:Date/doc
local p = {}
local monthData = mw.loadData( 'Module:Month/data' )
local h = require("Module:HF")
local getArgs = require('Dev:Arguments').getArgs
local language = mw.language.new('en')
local month_names = monthData[1]
local month_numbers = monthData[2]
local days_in_month = {31,28,31,30,31,30,31,31,30,31,30,31}
--------------------------------------------------------------------------------
function p.get_current_year()
return tonumber(language:formatDate('Y'))
end
--------------------------------------------------------------------------------
-- return full month name
function p.get_month_name(frame)
local args = getArgs(frame)
local name = args[1]
local output = nil
if not h.isempty(name)
then
name = mw.text.trim(name)
name = string.gsub(name, '^0', '')
output = month_names[ string.lower(name) ]
end
return output
end
--------------------------------------------------------------------------------
-- return month number
function p.get_month_number(frame)
local args = getArgs(frame)
local number = args[1]
local output = nil
if not h.isempty(number)
then
number = mw.text.trim(number)
number = string.gsub(number, '^0', '')
output = month_numbers[ string.lower(number) ]
end
return output
end
--------------------------------------------------------------------------------
--takes a date and formats it according to the syntax - https://www.mediawiki.org/wiki/Help:Extension:ParserFunctions##time
function p.lua_date_converter(s_date, s_format)
local year = nil
local month = nil
local day = nil
local i = 0
local j = 0
local output = ''
s_format = s_format or 'Ymd'
if h.isempty(s_date) or s_date == 'now'
then output = language:formatDate(s_format)
else
month, day, year = string.match(s_date, '(.+) (.+), (%d%d%d%d)')
if month == nil
then month, day, year = string.match(s_date, '(.+)%-(.+)%-(%d%d%d%d)')
end
if day ~= nil and month ~= nil and year ~= nil
then
month = p.get_month_number({month})
if #day == 1 then day = '0'..day end
if s_format == 'Ymd'
then output = year..month..day
elseif s_format == 'Ym'
then output = year..month
elseif s_format == 'F j, Y'
then
day = string.gsub(day, '^0', '')
month = p.get_month_name({month})
output = month..' '..day..', '..year
else output = language:formatDate(s_format, month..' '..day..' '..year)
end
else output = language:formatDate(s_format, s_date)
end
end
return output
end
--------------------------------------------------------------------------------
--compares two dates. Return "true" if 1st date is before the 2nd date, and "false" otherwise.
function p.lua_date_comparison(date1, date2)
local current_year = p.get_current_year()
local output
date1 = p.lua_date_converter(date1, 'Ymd')
if tonumber( string.sub(date1, 1, 4) ) < current_year
and ( h.isempty(date2)
or date2 == 'now'
or tonumber( string.sub(p.lua_date_converter(date2, 'Ymd'), 1, 4) ) >= current_year
)
then
output = true
else
date2 = p.lua_date_converter(date2 or 'now', 'Ymd') --If 2nd date is ommited, then current date is used for comparison.
output = date1<=date2
end
return output
end
--------------------------------------------------------------------------------
--returns era based on year
--[[
function p.get_era(frame)
local args = getArgs(frame)
local year = tonumber(args[1])
local key = args[2] or ''
local output = ''
if not h.isempty(year)
then
if not h.isempty(key) then key = ' '..key end
if year<1955 then output = 'Golden-Age'..key end
if year>=1955 and year<1970 then output = 'Silver-Age'..key end
if year>=1970 and year<1983 then output = 'Bronze-Age'..key end
if year>=1983 and year<1992 then output = 'Copper-Age'..key end
if year>=1992 then output = 'Modern-Age'..key end
end
return output
end
]]--
--------------------------------------------------------------------------------
function p.lua_get_publication_category(year, month, day, page_type)
local link = ''
local category = ''
local text = ''
if h.isempty(page_type)
then page_type = ''
end
if not h.isempty(year)
then
month = p.get_month_name({month})
if month ~= nil
then
if h.isempty(day)
then day = ''
else day = ' '..day
end
category = year..', '..month..page_type
link = h.LinkToCategory(category, month..day)..', '..h.LinkToCategory(year..page_type, year)
text = month..day..', '..year
else
category = year..page_type
link = h.LinkToCategory(year, year)
text = year
end
end
return link, category, text
end
--------------------------------------------------------------------------------
-- returns information about release date
function p.lua_get_release_date_info(release_date)
local recent = false
local releaseweek
local text = ''
local link = ''
local year = ''
local month = ''
local day = ''
local no_day = ''
local category = ''
local output = ''
if not h.isempty(release_date)
then
output = p.lua_date_converter(release_date, 'F j, Y')
month, day, year = string.match(output, '(.-) (%d-), (%d%d%d%d)')
no_day = month..', '..year
link = p.lua_get_link_to_release_week(output)
text = h.break_link(link, 1)
recent = p.lua_is_recently_released(output)
end
output = {
date = output,
week = {
text = text,
link = link
},
recent = recent,
day = day,
month = month,
year = year,
no_day = no_day
}
return output
end
--------------------------------------------------------------------------------
-- returns information about publication date
function p.lua_get_publication_date_info(year, month, canceled, page_type)
local function get_sortdate(year, month)
local month_number = p.get_month_number({month}) or '01'
local output = year
if output == ''
then output = '9999'
end
return output..'-'..month_number
end
local month_name = p.get_month_name({month}) or ''
local categories = {}
local link = ''
local category = ''
local output = ''
if not h.isempty(page_type) and page_type == 'Comic'
then page_type = ' Cover Date'
else page_type = ''
end
if h.isempty(year)
then year = ''
end
if year ~= ''
then
link, category = p.lua_get_publication_category(year, month_name, nil, page_type)
table.insert(categories, year..page_type)
table.insert(categories, category)
elseif not h.isempty(canceled) and not canceled
then table.insert(categories, 'Need Comic Dates')
end
output = {
link = link,
year = year,
month = month_name,
sortdate = get_sortdate(year, month),
}
return output, categories
end
--------------------------------------------------------------------------------
--check if comics, episode, movie, etc. was recently released/published
function p.isRecent(frame)
local args = getArgs(frame)
local release_date = args['releasedate']
local year = args['year']
local month = args['month']
local canceled = args['canceled'] or false
local output = false
if not canceled and (p.lua_is_recently_published(year, month) or p.lua_is_recently_released(release_date))
then output = true
end
return output
end
--------------------------------------------------------------------------------
function p.lua_is_recently_published(year, month)
local current_date = p.lua_date_converter()
local s
local publication_date
local output = false
if not h.isempty(year)
then
month = p.get_month_number({month}) or '01'
publication_date = year..month..'01'
s = language:formatDate('Ym', '-2 months')..'01'
if publication_date>=s and publication_date<=current_date
then output = true
end
end
return output
end
--------------------------------------------------------------------------------
function p.lua_is_recently_released(release_date)
local today = p.lua_date_converter('now', 'Ymd')
local output = false
if not h.isempty(release_date)
then
release_date = p.lua_date_converter(release_date, 'Ymd')
if release_date<=today and release_date>=language:formatDate('Ymd', '-1 month')
then output = true
end
end
return output
end
--------------------------------------------------------------------------------
function p.lua_is_recently_released_episode(year, month, day)
local release_date
local today = p.lua_date_converter('now', 'Ymd')
local output = false
if not h.isempty(year) and not h.isempty(month) and not h.isempty(day)
then
month = p.get_month_number({month})
day = string.rep( '0', 2-#tostring(day) )..day
release_date = year..month..day
if release_date<=today and release_date>=language:formatDate('Ymd', '-1 month')
then output = true
end
end
return output
end
--*************************************************************************************************
-- functions to manually calculate number of week (based on date) or date (based on number of week)
--------------------------------------------------------------------------------
-- return week number and year from "Week WW, YYYY" format
function p.lua_get_week_number_and_year_from_week_name(week_name)
local week_number
local year
week_number, year = string.match(week_name, 'Week (%d+), (%d%d%d%d)')
return tonumber(week_number), tonumber(year)
end
--------------------------------------------------------------------------------
function p.lua_get_week_name_from_week_number_and_year(week_number, year)
local output = ''
if not h.isempty(week_number) and not h.isempty(year)
then
if #tostring(week_number) == 1
then week_number = '0'..week_number
end
output = 'Week '..week_number..', '..year
end
return output
end
--------------------------------------------------------------------------------
function p.lua_is_leap_year(year)
local output = false
if math.fmod( year-1904, 4 ) == 0
then output = true
end
return output
end
--------------------------------------------------------------------------------
function p.lua_get_day_of_year(year, month, day)
local output = day
for i = 1, month-1 do
output = output + days_in_month[i]
end
if p.lua_is_leap_year(year) and month > 2
then output = output + 1
end
return output
end
--------------------------------------------------------------------------------
function p.lua_get_date_from_day_of_year(day_of_year, year)
local i = 1
local j
local leap_year = p.lua_is_leap_year(year)
local output
if day_of_year > 366 and leap_year
then
day_of_year = day_of_year - 366
year = year + 1
elseif day_of_year > 365 and not leap_year
then
day_of_year = day_of_year - 365
year = year + 1
elseif day_of_year < 0
then
year = year - 1
leap_year = p.lua_is_leap_year(year)
if leap_year
then day_of_year = day_of_year + 366
else day_of_year = day_of_year + 365
end
end
if day_of_year == 0
then output = 'December 31, '..year-1
else
output = day_of_year
j = days_in_month[1]
while output > j do
output = output - j
i = i + 1
if i == 2 and leap_year
then j = 29
else j = days_in_month[i]
end
end
output = p.get_month_name({i})..' '..output..', '..year
end
return output
end
--------------------------------------------------------------------------------
-- return day of week for January 1 (1 = Monday, 7 = Sunday, etc.)
-- day of week repeats every 28 years
function p.lua_get_day_of_week_of_january_1(year)
local output = {5,7,1,2,3,5,6,7,1,3,4,5,6,1,2,3,4,6,7,1,2,4,5,6,7,2,3,4}
local year_number = math.fmod( year-1904, 28 ) + 1
return output[year_number]
end
--------------------------------------------------------------------------------
-- return first day of the year's first week. If it started in december of the previous year, then negative number is returned (for example, first week of 2020 year started on December 30, 2019, so function returns -2)
function p.lua_get_first_day_of_first_week_of_year(year)
local first_day = p.lua_get_day_of_week_of_january_1(year)
return math.fmod( 11-first_day, 7) - 3
end
--------------------------------------------------------------------------------
function p.lua_get_day_of_week(year, month, day)
local first_day = p.lua_get_day_of_week_of_january_1(year)
local day_of_year = p.lua_get_day_of_year(year, month, day)
local output
output = math.fmod(first_day + day_of_year - 1, 7 )
if output == 0
then output = 7
end
return output
end
--------------------------------------------------------------------------------
function p.lua_get_week_number(year, month, day)
local day_of_year = p.lua_get_day_of_year(year, month, day)
local day_of_week = p.lua_get_day_of_week(year, month, day)
local week_number = math.floor( (day_of_year - day_of_week + 10) / 7 )
local output
if week_number == 0
then
year = year - 1
week_number = p.lua_get_last_week_of_year2(year)
elseif week_number == 53 and p.lua_get_last_week_of_year2(year) == 52
then
year = year + 1
week_number = 1
end
output = p.lua_get_week_name_from_week_number_and_year(week_number, year)
return output
end
--------------------------------------------------------------------------------
-- return date of Wednesday for "year"'s week
function p.lua_get_date_from_week_number(week_number, year)
local first_day_of_first_week
local i = 1
local leap_year
local first_day
local last_week = p.lua_get_last_week_of_year2(year)
local month
local output
if week_number > last_week
then
week_number = week_number - last_week
year = year + 1
end
first_day_of_first_week = p.lua_get_first_day_of_first_week_of_year(year)
leap_year = p.lua_is_leap_year(year)
first_day = p.lua_get_day_of_week_of_january_1(year)
output = first_day_of_first_week + 7 * (week_number-1) + 3
output = p.lua_get_date_from_day_of_year(output, year)
return output
end
--------------------------------------------------------------------------------
function p.lua_get_last_week_of_year(year)
local function week_number(y)
local output = y + (y / 4) - (y / 100) + (y / 400)
return math.floor( math.fmod(output, 7) )
end
if week_number(year) == 4 or week_number(year - 1) == 3
then return 53
else return 52
end
end
--------------------------------------------------------------------------------
function p.lua_get_last_week_of_year2(year)
local first_day = p.lua_get_day_of_week_of_january_1(year)
local last_day = p.lua_get_day_of_week(year, 12, 31)
local leap_year = p.lua_is_leap_year(year)
if ( not leap_year and (first_day == 4 or last_day == 4) ) or ( leap_year and (first_day == 3 or last_day == 5) )
then return 53
else return 52
end
end
--*************************************************************************************************
--------------------------------------------------------------------------------
function p.lua_get_previous_next_weeks(week_number, year)
local previous_week
local next_week
if week_number == 1
then previous_week = p.lua_get_date_from_week_number(p.lua_get_last_week_of_year2(year - 1), year - 1)
else previous_week = p.lua_get_date_from_week_number(week_number - 1, year)
end
if week_number == p.lua_get_last_week_of_year2(year)
then next_week = p.lua_get_date_from_week_number(1, year + 1)
else next_week = p.lua_get_date_from_week_number(week_number + 1, year)
end
return previous_week, next_week
end
--------------------------------------------------------------------------------
function p.get_previous_next_weeks(frame)
local design = require("Module:Design")
local current_date = p.lua_get_release_week_from_release_date( p.lua_date_converter() )
local pagename = mw.title.getCurrentTitle().text
local link
local category = true
local previous_week
local next_week
local output = ''
week_number, year = p.lua_get_week_number_and_year_from_week_name(pagename)
if week_number == nil or year == nil
then
week_number, year = p.lua_get_week_number_and_year_from_week_name(current_date)
category = false
end
previous_week, next_week = p.lua_get_previous_next_weeks(week_number, year)
link = p.lua_get_release_week_from_release_date(previous_week)
previous_week = h.LinkToCategory(link, previous_week)
link = p.lua_get_release_week_from_release_date(next_week)
next_week = h.LinkToCategory(link, next_week)
pagename = p.lua_get_date_from_week_number(week_number, year)
output = previous_week..' — '..pagename..' — '..next_week
output = output .. '<br>' .. tostring(mw.html.create('span'):addClass('messagebox__help'):wikitext('See Also: ' .. h.LinkToCategory('Active Volumes', 'list of currently active series')))
output = design.messagebox({ output })
if category
then
category = p.lua_get_date_from_week_number(week_number, year)
category = string.gsub(category, ' %d+, ', ', ')
category = 'Comics Released in '..category
output = output..h.Category(category)
end
return output
end
--------------------------------------------------------------------------------
function p.lua_get_release_week_from_release_date(release_date)
local year
local month
local day
local output = ''
if not h.isempty(release_date)
then
release_date = p.lua_date_converter(release_date, 'F j, Y')
month, day, year = string.match(release_date, '(.-) (%d-), (%d%d%d%d)')
month = tonumber( p.get_month_number({month}) )
output = p.lua_get_week_number(year, month, day)
end
return output
end
--------------------------------------------------------------------------------
-- used in Template:ReleaseWeek
function p.get_release_week_from_release_date(frame)
local args = getArgs(frame)
local release_date = args[1]
local output
if h.isempty(release_date)
then output = p.lua_get_release_week_from_release_date( p.lua_date_converter() ) -- current date
else output = p.lua_get_release_week_from_release_date(release_date)
end
return output
end
--------------------------------------------------------------------------------
function p.lua_get_link_to_release_week(release_date, week_number, year)
local month
local day
local output = ''
if not h.isempty(release_date)
then
release_date = p.lua_date_converter(release_date, 'F j, Y')
week_number = p.lua_get_release_week_from_release_date(release_date)
output = h.LinkToCategory(week_number, release_date)
elseif not h.isempty(week_number) and not h.isempty(year)
then
release_date = p.lua_get_date_from_week_number(week_number, year)
week_number = p.lua_get_week_name_from_week_number_and_year(week_number, year)
output = h.LinkToCategory(week_number, release_date)
end
return output
end
--------------------------------------------------------------------------------
function p.lua_get_release_week_category(release_date)
local week
local output = ''
week = p.lua_get_release_week_from_release_date(release_date)
if week ~= ''
then output = h.Category(week)
end
return output
end
return p