Module:Date

-- credit: Marvel Database (marvel.fandom.com) 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}

-- 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 output date1 = p.lua_date_converter(date1, 'Ymd') if tonumber( string.sub(date1, 1, 4) ) < 2020 and (  h.isempty(date2) 				or date2 == 'now' 				or tonumber( string.sub(p.lua_date_converter(date2, 'Ymd'), 1, 4) ) >= 2020			) 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) local link = '' local category = '' local text = ''

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 link = h.LinkToCategory(category, month..day)..', '..h.LinkToCategory(year, year) text = month..', '..year else category = year 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) --local published = true local month_number local month_name local categories = {} local link = '' local category = '' local sortdate = '' local output = '' month_number = p.get_month_number({month}) or '01' month_name = p.get_month_name({month}) or ''

if h.isempty(year) then year = '' end if year ~= '' then sortdate = year..month_number..'01' --published = p.lua_date_comparison(sortdate) sortdate = ' '..sortdate link, category = p.lua_get_publication_category(year, month_name) table.insert(categories, year) table.insert(categories, category) table.insert(categories, p.get_era({year})) 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 = sortdate, --published = published, }	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', '-4 months') 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', '-2 weeks') 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 = design.messagebox({ previous_week..' &mdash;  '..pagename..'  &mdash;  '..next_week }) 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

-- used in Template:Month Category function p.get_previous_and_next_month(frame) local pagename = mw.title.getCurrentTitle.text local year local month local month_number local next_month local previous_month local design = require("Module:Design") local output = '' year, month = string.match(pagename, '(%d+), (.+)') if year ~= nil and month ~= nil then year = tonumber(year) month_number = tonumber( p.get_month_number({month}) ) if month_number == 1 then previous_month = tostring(year - 1)..', December' next_month = tostring(year)..', February' elseif month_number == 12 then previous_month = tostring(year)..', November' next_month = tostring(year+1)..', January' else previous_month = tostring(year)..', '..p.get_month_name({month_number-1}) next_month = tostring(year)..', '..p.get_month_name({month_number+1}) end previous_month = h.LinkToCategory(previous_month, previous_month) next_month = h.LinkToCategory(next_month, next_month) output = design.messagebox({previous_month..' — '..pagename..' — '..next_month}) output = output..h.Category(year, year..' '..p.get_month_number({month})) end return output end

return p