Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

// request.cf · coarse context

A page that knows where it met you.

Only coarse request metadata is shown. This demo does not display or persist visitor IP addresses.

Country
US
Cloudflare location
CMH
Connection
HTTP/2
Language
Not provided

Ray ID: a24a07832a54c20a

Jump to content

Module:Countdown2/sandbox

From Wikipedia, the free encyclopedia
--- This module powers {{tl|countdown2}}.
--
-- The module takes in two primary arguments, time and offset, and returns
-- a formatted countdown string corresponding to the duration of the countdown.
--
-- @require Module:Arguments
-- @require Module:Yesno
-- @release beta

local p = {}

-- Constants
local lang = mw.language.getContentLanguage()
local getArgs = require('Module:Arguments').getArgs
local yn = require("Module:Yesno")
local round = math.floor
local mod = math.fmod

local function isLeapYear(year)
	return mod(year, 4) == 0 and
		(mod(year, 100) ~= 0 or
			(mod(year, 400) == 0))
end

p._isLeapYear = isLeapYear

local function numberOfDaysInYear(year)
	if isLeapYear(year) then
		return 366
	else
		return 365
	end
end

local function yearIncr(timestamp)
	local date = os.date("!*t", timestamp)
	if date.month >= 3 or (date.month == 2 and date.day == 28) then
		return numberOfDaysInYear(date.year + 1)
	else
		return numberOfDaysInYear(date.year)
	end
end

local function numberOfDaysInMonth(year, month)
	if month == 9 or month == 4 or month == 6 or month == 11 then
		return 30
	elseif month == 2 then
		if isLeapYear(year) then
			return 29
		else
			return 28
		end
	else
		return 31
	end
end

local function monthIncr(timestamp)
	local date = os.date("!*t", timestamp)
	if date.day >= 28 then
		return numberOfDaysInMonth(date.year, round(mod(date.month - 1, 12) + 1) + 1)
	else
		return numberOfDaysInMonth(date.year, date.month)
	end
end

--- Entrypoint for the module.
--
-- @param {table} frame current frame
-- @param {table} args current arguments
-- @param {string} args.before text to prepend to countdown
-- @param {string} args.after text to append to countdown
-- @param {string} args.time time argument
-- @param {string} args.end what to show when the countdown is over
-- @param {string} args.offset offset argument
-- @param {boolean} args.shorthand whether to use shorthand units
-- @param {number} args.precision the number of units to use
-- @param {boolean} args.purge whether to show a purge link
-- @param {string} args.style inline styles to apply to countdown text
-- @return the output wikitext
function p.main(frame, args)
	args = args or getArgs(frame)
	local timeInput = args['time'] or args[1] or error("No time string specified!")
	local offset = args['offset'] or args[2] or ''
	local atEnd = args[3] or args['end'] or ''
	local shorthand = yn(args['shorthand'] == nil and 'false' or args['shorthand'], false)
	local numberOfUnitsToShow = tonumber(args['precision']) or math.huge
	local showPurgeLink = yn(args['purge'] == nil and 'true' or args['purge'])
	local timestamp = tonumber(frame:preprocess("{{#time:U|" .. timeInput .. ' ' .. offset .. "|}}"))
	local currentTime = tonumber(frame:preprocess("{{#time:U}}"))
	if timestamp - currentTime <= 0 then
		return atEnd
	end

	local dateTo = os.date("!*t", timestamp)
	local dateFrom = os.date("!*t", currentTime)

	local time_days = round((timestamp - currentTime) / 86400)
	local time_hours = round(mod((timestamp - currentTime) / 3600, 24))
	local time_minutes = round(mod((timestamp - currentTime) / 60, 60))
	local time_seconds = round(mod((timestamp - currentTime), 60))

	local time_years = 0
	while time_days - yearIncr(os.time(dateFrom)) >= 0 do
		time_years = time_years + 1
		time_days = time_days - yearIncr(os.time(dateFrom))
		dateFrom.year = dateFrom.year + 1
	end
	local time_months = 0
	while time_days - monthIncr(os.time(dateFrom)) >= 0 do
		time_months = time_months + 1
		time_days = time_days - monthIncr(os.time(dateFrom))
		dateFrom.month = dateFrom.month + 1
		if (dateFrom.month == 13) then
			dateFrom.year = dateFrom.year + 1
			dateFrom.month = 1
		end
	end
	local time_weeks = round(time_days / 7)
	time_days = time_days - time_weeks * 7

	local yearNode = mw.html.create('span')
		:addClass('countdown2-year')
	local monthNode = mw.html.create('span')
		:addClass('countdown2-month')
	local weekNode = mw.html.create('span')
		:addClass('countdown2-week')
	local dayNode = mw.html.create('span')
		:addClass('countdown2-day')
	local hourNode = mw.html.create('span')
		:addClass('countdown2-hour')
	local minuteNode = mw.html.create('span')
		:addClass('countdown2-minute')
	local secondNode = mw.html.create('span')
		:addClass('countdown2-second')
	local out = {}
	if shorthand then
		-- clip the first letter or two of each display
		local secondDisplay, minuteDisplay, hourDisplay, dayDisplay, weekDisplay, monthDisplay, yearDisplay
		secondDisplay = mw.ustring.sub(frame:preprocess(mw.message.new("seconds", ""):plain()), 0, 1)
		minuteDisplay = mw.ustring.sub(frame:preprocess(mw.message.new("minutes", ""):plain()), 0, 1)
		hourDisplay = mw.ustring.sub(frame:preprocess(mw.message.new("hours", ""):plain()), 0, 1)
		dayDisplay = mw.ustring.sub(frame:preprocess(mw.message.new("days", ""):plain()), 0, 1)
		weekDisplay = mw.ustring.sub(frame:preprocess(mw.message.new("weeks", ""):plain()), 0, 1)
		monthDisplay = mw.ustring.sub(frame:preprocess(mw.message.new("months", ""):plain()), 0, 2)
		yearDisplay = mw.ustring.sub(frame:preprocess(mw.message.new("years", ""):plain()), 0, 1)

		yearNode:wikitext( time_years .. yearDisplay ):done()
		monthNode:wikitext( time_months .. monthDisplay ):done()
		weekNode:wikitext( time_weeks .. weekDisplay ):done()
		dayNode:wikitext( time_days .. dayDisplay ):done()
		hourNode:wikitext( time_hours .. hourDisplay ):done()
		minuteNode:wikitext( time_minutes .. minuteDisplay ):done()
		secondNode:wikitext( time_seconds .. secondDisplay ):done()
	else
		yearNode:wikitext( mw.message.new("years", time_years):plain() )
		monthNode:wikitext( mw.message.new("months", time_months):plain() )
		weekNode:wikitext( mw.message.new("weeks", time_weeks):plain() )
		dayNode:wikitext( mw.message.new("days", time_days):plain() )
		hourNode:wikitext( mw.message.new("hours", time_hours):plain() )
		minuteNode:wikitext( mw.message.new("minutes", time_minutes):plain() )
		secondNode:wikitext( mw.message.new("seconds", time_seconds):plain() )
	end
	if time_years > 0 and numberOfUnitsToShow > 0 then
		numberOfUnitsToShow = numberOfUnitsToShow - 1
	else
		yearNode:css({ display = 'none' })
	end
	if time_months > 0 and numberOfUnitsToShow > 0 then
		numberOfUnitsToShow = numberOfUnitsToShow - 1
	else
		monthNode:css({ display = 'none' })
	end
	if time_weeks > 0 and numberOfUnitsToShow > 0 then
		numberOfUnitsToShow = numberOfUnitsToShow - 1
	else
		weekNode:css({ display = 'none' })
	end
	if time_days > 0 and numberOfUnitsToShow > 0 then
		numberOfUnitsToShow = numberOfUnitsToShow - 1
	else
		dayNode:css({ display = 'none' })
	end
	if time_hours > 0 and numberOfUnitsToShow > 0 then
		numberOfUnitsToShow = numberOfUnitsToShow - 1
	else
		hourNode:css({ display = 'none' })
	end
	if time_minutes > 0 and numberOfUnitsToShow > 0 then
		numberOfUnitsToShow = numberOfUnitsToShow - 1
	else
		minuteNode:css({ display = 'none' })
	end
	if time_seconds > 0 and numberOfUnitsToShow > 0 then
	else
		secondNode:css({ display = 'none' })
	end
	table.insert(out, tostring( yearNode ))
	table.insert(out, tostring( monthNode ))
	table.insert(out, tostring( weekNode ))
	table.insert(out, tostring( dayNode ))
	table.insert(out, tostring( hourNode ))
	table.insert(out, tostring( minuteNode ))
	table.insert(out, tostring( secondNode ))

	return frame:preprocess('<span class="countdown2" data-countdown-shorthand="' .. tostring(shorthand) .. '" data-countdown-timestamp="' .. timestamp .. '" data-num-units="' .. ((tonumber(args['precision']) or math.huge) == math.huge and #out or tonumber(args['precision'])) .. '><span class="countdown2-before">' .. (args['before'] or '') .. '</span> <span class="countdown2-countdown" style="' .. (args['style'] or '') .. '">'
		.. table.concat(out, " ") .. '</span> <span class="countdown2-after">' .. (args['after'] or '') .. "</span>"
		.. ((#out > 0 and showPurgeLink) and '<span class="countdown2-purgelink plainlinks"> ([{{fullurl:{{FULLPAGENAMEE}}|action=purge}} update])</span>' or '') .. '<span class="countdown2-end" style="display:none;">' .. atEnd .. '</span></span>')
end

return p