Module:Countdown2/sandbox
| This is the module sandbox page for Module:Countdown2 (diff). |
| This template is currently being deleted. This template is being removed from the pages on which it is currently used, after which it will be deleted. Please check Wikipedia:Templates for discussion/Holding cell for any additional instructions. Please do not use it on any additional pages, but do not remove it from pages if it is under deletion review. The decision to delete this template was made following this discussion initiated on 22 April 2026 at Templates for discussion. Administrators: Please review this template's instructions at Wikipedia:Templates for discussion/Holding cell before proceeding with any action. |
| This module is rated as beta. It is considered ready for widespread use, but as it is still relatively new, it should be applied with some caution to ensure results are as expected. |
| This module depends on the following other modules: |
| Description | This module powers {{countdown2}}. |
|---|---|
| Status | Beta |
| Updated | June 1, 2026 (7 days ago) |
| Dependencies |
This module powers {{countdown2}}. The module takes in two primary arguments, time and offset, and returns a formatted countdown string corresponding to the duration of the countdown.
Documentation
Package items
countdown2.main( frame, args )(function)- Entrypoint for the module.
- Parameters:
framecurrent frame (table)argscurrent arguments (table)args.beforetext to prepend to countdown (string)args.aftertext to append to countdown (string)args.timetime argument (string)args.endwhat to show when the countdown is over (string)args.offsetoffset argument (string)args.shorthandwhether to use shorthand units (boolean)args.precisionthe number of units to use (number)args.purgewhether to show a purge link (boolean)args.styleinline styles to apply to countdown text (string)
- Returns: the output wikitext
Documentation above is auto generated
--- 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
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.