Skip to content

Latest commit

 

History

History
147 lines (130 loc) · 5.83 KB

os [DEPRECATED].md

File metadata and controls

147 lines (130 loc) · 5.83 KB
-- Extends the os table to include the full os.date functionality included in vanilla Lua
-- @readme https://github.com/RoStrap/Time/blob/master/README.md
-- @author Validark

-- Necessary string tables
local dayNames = {[0] = "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
local months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}

-- Localize functions
local time = os.time
local floor, sub, find, gsub, format = math.floor, string.sub, string.find, string.gsub, string.format
local type, tick, tonumber = type, tick, tonumber

local function date(formatString, unix)
	--- Allows you to use os.date in RobloxLua!
	--		date ([format [, time]])
	-- This doesn't include the explanations for the math. If you want to see how the numbers work, see the following:
	-- http://howardhinnant.github.io/date_algorithms.html#civil_from_days
	--
	-- @param string formatString
	--		If present, function date returns a string formatted by the tags in formatString.
	--		If formatString starts with "!", date is formatted in UTC.
	--		If formatString is "*t", date returns a table
	--		Placing "_" in the middle of a tag (e.g. "%_d" "%_I") removes padding
	--		String Reference: https://github.com/Narrev/NevermoreEngine/blob/patch-5/Modules/Utility/readme.md
	--		@default "%c"
	--
	-- @param number unix
	--		If present, unix is the time to be formatted. Otherwise, date formats the current time.
	--		The amount of seconds since 1970 (negative numbers are occasionally supported)
	--		@default tick()

	-- @returns a string or a table containing date and time, formatted according to the given string format. If called without arguments, returns the equivalent of date("%c").

	-- Find whether formatString was used
	if formatString then
		if type(formatString) == "number" then -- If they didn't pass a formatString, and only passed unix through
			if type(unix) == "string" then error("Invalid parameters passed to os.date. Your parameters might be in the wrong order") end
			unix, formatString = formatString, "%c"
		elseif type(formatString) == "string" then
			if not find(formatString, "*t") and not find(formatString, "%%[_cxXTrRaAbBdHIjMmpsSuwyY]") then
				warn("[os.date] \"" .. formatString .. "\" has nothing to format")
			end
			local UTC
			formatString, UTC = gsub(formatString, "^!", "") -- If formatString begins in '!', use os.time()
			if UTC == 1 and unix then warn("Cannot determine time to format for os.date: Use either an \"!\" at the beginning of the string OR pass a time parameter") end
			unix = unix or UTC == 1 and time()
		end
	else -- If they did not pass a formatting string
		formatString = "%c"
	end

	-- Set unix
	unix = tonumber(unix) or tick()

	-- Get hours, minutes, and seconds
	local hours, minutes, seconds = floor(unix / 3600 % 24), floor(unix / 60 % 60), floor(unix % 60)

	-- Get days, month and year
	local days = floor(unix / 86400) + 719468
	local wday = (days + 3) % 7 -- Day of week with Sunday @0 [0, 6]
	local year = floor((days >= 0 and days or days - 146096) / 146097) -- 400 Year bracket
	days = (days - year * 146097) -- Days into 400 year bracket [0, 146096]
	local years = floor((days - floor(days/1460) + floor(days/36524) - floor(days/146096))/365)	-- Years into 400 Year bracket[0, 399]
	days = days - (365*years + floor(years/4) - floor(years/100)) -- Days into year with March 1st @0 [0, 365]
	local month = floor((5*days + 2)/153) -- Month with March @0 [0, 11]
	local yday = days
	days = days - floor((153*month + 2)/5) + 1 -- Days into month [1, 31]
	month = month + (month < 10 and 3 or -9) -- Actual month [1, 12]
	year = years + year*400 + (month < 3 and 1 or 0) -- Actual Year


	if formatString == "*t" then -- Return a table if "*t" was used
		return {year = year, month = month, day = days, yday = yday, wday = wday, hour = hours, min = minutes, sec = seconds}
	end

	-- Return formatted string
	return (gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(gsub(formatString,
		"%%c",  "%%x %%X"),
		"%%_c", "%%_x %%_X"),
		"%%x",  "%%m/%%d/%%y"),
		"%%_x", "%%_m/%%_d/%%y"),
		"%%X",  "%%H:%%M:%%S"),
		"%%_X", "%%_H:%%M:%%S"),
		"%%T",  "%%I:%%M %%p"),
		"%%_T", "%%_I:%%M %%p"),
		"%%r",  "%%I:%%M:%%S %%p"),
		"%%_r", "%%_I:%%M:%%S %%p"),
		"%%R",  "%%H:%%M"),
		"%%_R", "%%_H:%%M"),
		"%%a", sub(dayNames[wday], 1, 3)),
		"%%A", dayNames[wday]),
		"%%b", sub(months[month], 1, 3)),
		"%%B", months[month]),
		"%%d", format("%02d", days)),
		"%%_d", days),
		"%%H", format("%02d", hours)),
		"%%_H", hours),
		"%%I", format("%02d", hours > 12 and hours - 12 or hours == 0 and 12 or hours)),
		"%%_I", hours > 12 and hours - 12 or hours == 0 and 12 or hours),
		"%%j", format("%02d", yday)),
		"%%_j", yday),
		"%%M", format("%02d", minutes)),
		"%%_M", minutes),
		"%%m", format("%02d", month)),
		"%%_m", month),
		"%%n", "\n"),
		"%%p", hours >= 12 and "pm" or "am"),
		"%%_p", hours >= 12 and "PM" or "AM"),
		"%%s", (days < 21 and days > 3 or days > 23 and days < 31) and "th" or ({"st", "nd", "rd"})[days % 10]),
		"%%S", format("%02d", seconds)),
		"%%_S", seconds),
		"%%t", "\t"),
		"%%u", wday == 0 and 7 or wday),
		"%%w", wday),
		"%%Y", year),
		"%%y", format("%02d", year % 100)),
		"%%_y", year % 100),
		"%%%%", "%%")
	)
end

local function clock()
	return workspace.DistributedGameTime
end

local function isLeapYear(year)
	return year % 4 == 0 and (year % 25 ~= 0 or year % 16 == 0)
end

local monthLengths = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

local function monthLength(month, year)
	return month == 2 and isLeapYear(year) and 29 or monthLengths[month]
end

local os = {
	date = date;
	clock = clock;
	__index = os;
	isLeapYear = isLeapYear;
	monthLength = monthLength;
}

return setmetatable(os, os)