Halo Esports Wiki
Advertisement
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Documentation for this module may be created at Module:TimeUtil/doc

local lang = mw.getLanguage('en')
local util_table = require('Module:TableUtil')
local util_vars = require("Module:VarsUtil")
local Date = require('Module:Date')
local SECONDS_IN_DAY = 24 * 60 * 60

local TZLIST = { 'PST', 'CET', 'AEST', 'UTC' }
local DAYS_PER_WEEK = 7

local h = {}

function h.printDelta(delta)
	return delta > 0 and ('+' .. delta) or delta
end

local p = {}

p.monthNumberToTri = { 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' }

p.monthNumberToName = { 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' }

p.monthNameToNumber = util_table.hash(p.monthNumberToName)

p.toUTC = {
	[true] = { PST = 7, CET = -2, AEST = -10, UTC = 0 },
	[false] = { PST = 8, CET = -1, AEST = -11, UTC = 0 },
	yes = { PST = 7, CET = -2, AEST = -10, UTC = 0 },
	no = { PST = 8, CET = -1, AEST = -11, UTC = 0 },
	spring = { PST = 7, CET = -1, AEST = -10, UTC = 0 },
	fall = { PST = 7, CET = -1, AEST = -10, UTC = 0 },
}

function p.strToTime(str)
	local year, month, day, hour, minute, second = string.match(str, "(%d%d%d%d)%-(%d%d)%-(%d%d) (%d%d):(%d%d):?(%d?%d?)")
	return {
		year = year,
		month = month,
		day = day,
		hour = hour, 
		min = minute,
		sec = second
	}
end

function p.strToDate(str)
	local year, month, day = string.match(str, "(%d%d%d%d)-(%d%d)-(%d%d)")
	return {
		year = year,
		month = month,
		day = day
	}
end

function p.strToDateStr(str)
	if not str then return nil end
	local date = str:match("(%d%d%d%d%-%d%d%-%d%d)")
	return date
end

function p.strToTimeStr(str)
	if not str then return nil end
	return str:match('%d%d:%d%d')
end

function p.strToDateFuzzy(str)
	local year, month, day = str:match('(....)-(..)-(..)')
	return {
		year = tonumber(year),
		month = tonumber(month),
		day = tonumber(day)
	}
end

function p.strToYearNumber(str)
	if not str then return nil end
	local year = str:match('(%d%d%d%d)%-')
	if not year then return nil end
	return tonumber(year)
end

function p.strToDateStrFuzzy(str, isApprox)
	local year, month, day = str:match('(....)%-(..)%-(..)')
	if not year and not month and not day then
		error(('Bad fuzzy date: %s'):format(str))
	end
	year = tonumber(year)
	month = tonumber(month)
	day = tonumber(day)
	local suffix = isApprox and ' (approx.)' or ''
	if not month and not day then
		return year .. suffix
	elseif not day then
		return lang:formatDate('F Y', ('%s-%s-01'):format(year, month))  .. suffix
	end
	return lang:formatDate('j F Y', str) .. suffix
end

function p.strToDateStrFuzzyWithoutYear(str, isApprox)
	local year, month, day = str:match('(....)%-(..)%-(..)')
	if not year and not month and not day then
		error(('Bad fuzzy date: %s'):format(str))
	end
	year = tonumber(year)
	month = tonumber(month)
	day = tonumber(day)
	local suffix = isApprox and ' (approx.)' or ''
	if not year then return 'Unknown date' end
	if not month and not day then
		return year .. suffix
	elseif not day then
		return lang:formatDate('F', ('%s-%s-01'):format(year, month))  .. suffix
	end
	return lang:formatDate('F j', str) .. suffix
end

function p.isInFuture(str, intervalSeconds)
	if not intervalSeconds then intervalSeconds = 0 end
	return os.difftime(os.time(p.strToTime(str)),os.time()) > intervalSeconds
end

function p.dateIsInFuture(str, intervalSeconds)
	if not intervalSeconds then intervalSeconds = 0 end
	local time = p.strToDateFuzzy(str)
	if time.day == '??' then time.day = 31 end
	if time.month == '??' then time.month = 12 end
	return os.difftime(os.time(time),os.time()) > intervalSeconds
end

function p.dateIsInFutureOrNow(str, intervalSeconds)
	local time = p.strToDateFuzzy(str)
	if time.day == '??' then time.day = 31 end
	if time.month == '??' then time.month = 12 end
	return os.difftime(os.time(time),os.time()) > -1 / 2 * SECONDS_IN_DAY
end

function p.dateInLocal(str)
	local tbl = mw.html.create('span'):addClass('DateInLocal'):wikitext(lang:formatDate('Y,n,d,H,i', str))
	return tostring(tbl)
end

function p.dateOnlyInLocal(str)
	local tbl = mw.html.create('span'):addClass('DateOnlyInLocal'):wikitext(lang:formatDate('Y,n,d,H,i', str))
	return tostring(tbl)
end

function p.dateInLocalMatches(str)
	local tbl = mw.html.create('span'):addClass('DateInLocalMatches'):wikitext(lang:formatDate('Y,n,d,H,i', str))
	return tostring(tbl)
end

function p.timeInLocal(str)
	local tbl = mw.html.create('span'):addClass('TimeInLocal'):wikitext(lang:formatDate('Y,n,d,H,i', str))
	return tostring(tbl)
end

function p.countdown(str, args)
	if not args then args = {} end
	local i = args.i or ''
	local data_end = args.data_end or 'remove'
	local options = args.options and table.concat(args.options, ' ') or 'no-leading-zeros'
	local tbl = mw.html.create()
	tbl:tag('span')
		:attr('data-end', data_end)
		:attr('data-options',options)
		:attr('data-toggle','.post-countdown' .. i)
		:addClass('countdown')
		:css('display','none')
		:tag('span')
			:addClass('countdowndate')
			:wikitext(lang:formatDate('j F Y H:i:s', str) .. ' +0000')
	tbl:tag('span')
		:addClass('post-countdown' .. i)
		:css('display','none')
		:wikitext(args.default or '-')
	return tostring(tbl)
end

function p.unix(str)
	if type(str) == 'table' then
		str = p.strFromTable(str)
	end
	return lang:formatDate('U', str)
end

function p.unixNumber(str)
	if not str then return nil end
	return tonumber(p.unix(str))
end

function p.age(bday, death)
	if type(bday) == 'string' then
		bday = p.strToDate(bday)
	end
	for k, v in pairs(bday) do
		bday[k] = tonumber(v)
	end
	if type(death) == 'string' then
		death = p.unixNumber(death)
	end
	if not bday.year or not bday.month or not bday.day then return end
	local now = os.date('*t', death)
	local bdaypast = now.month > bday.month or now.month == bday.month and now.day >= bday.day
	return now.year - bday.year - 1 + (bdaypast and 1 or 0)
end

function p.getTimezones(str, init_tz, dst)
	if type(dst) == 'string' then
		dst = dst:lower()
	end
	if not p.toUTC[dst] then
		error(('Invalid timezone value of %s. Allowed values: yes, no, spring, fall.'):format(dst))
	end
	local delta = p.toUTC[dst][init_tz]
	local utc = lang:formatDate('Y-m-d H:i', ('%s %s hours'):format(str, h.printDelta(delta)))
	local tbl = { UTC = utc }
	for _, v in pairs(TZLIST) do
		delta = -1 * p.toUTC[dst][v]
		tbl[v] = lang:formatDate('Y-m-d H:i', ('%s %s hours'):format(utc, h.printDelta(delta)))
	end
	tbl.UTC = utc
	return tbl
end

function p.addTimezonesToRowFromUTC(row)
	-- overwrite a row's timezones to add PST, AEST, and CET
	local timezones = p.getTimezones(row.UTC, 'UTC', row.DST)
	util_table.merge(row, timezones)
end

function p.strFromTable(dt, format)
	local str = os.date('%Y-%m-%d', os.time(dt))
	if not format then return str end
	return lang:formatDate(format, str)
end

function p.getDatesInAWeek(date)
	local sunday = lang:formatDate('Y-m-d', ('%s - %s days'):format(
		date,
		lang:formatDate('w', date)
	))
	local tbl = {}
	for offset = 0, DAYS_PER_WEEK - 1 do
		tbl[#tbl+1] = lang:formatDate('Y-m-d', ('%s + %s days'):format(sunday, offset))
	end
	return tbl
end

return p
Advertisement