local C={}C.__index=C local p=(game:GetService("\082\117\110\083\101\114\118\105\099\101")):IsServer()local d={"\083\117\110\100\097\121";"\077\111\110\100\097\121";"\084\117\101\115\100\097\121";"\087\101\100\110\101\115\100\097\121";"\084\104\117\114\115\100\097\121","\070\114\105\100\097\121";"\083\097\116\117\114\100\097\121"}local x={"\083\117\110";"\077\111\110";"\084\117\101";"\087\101\100","\084\104\117","\070\114\105","\083\097\116"}local I={"\074\097\110\117\097\114\121";"\070\101\098\114\117\097\114\121";"\077\097\114\099\104";"\065\112\114\105\108","\077\097\121","\074\117\110\101";"\074\117\108\121";"\065\117\103\117\115\116","\083\101\112\116\101\109\098\101\114";"\079\099\116\111\098\101\114";"\078\111\118\101\109\098\101\114","\068\101\099\101\109\098\101\114"}local X={"\074\097\110";"\070\101\098";"\077\097\114","\065\112\114";"\077\097\121","\074\117\110";"\074\117\108","\065\117\103";"\083\101\112","\079\099\116";"\078\111\118";"\068\101\099"}function CopyTable(C)local p={}for C,d in pairs(C)do p[C]=d end return p end function C.new(d,x)if d~=nil then assert(type(d)=="\110\117\109\098\101\114","\'\115\101\099\111\110\100\115\' \097\114\103\117\109\101\110\116 \035\049 \109\117\115\116 \098\101 \097 \110\117\109\098\101\114")else d=tick()end local I=p if x~=nil then I=x end local X=os.date(I and"\033\042\116"or"\042\116",d)local g=setmetatable({Hour=X.hour;Minute=X.min,Weekday=X.wday,Day=X.day;Month=X.month,Year=X.year;Second=X.sec;Millisecond=math.floor((d%1)*1000),Yearday=X.yday;IsDST=X.isdst;_d=X,_s=d},C)return g end function C.fromJSON(p)assert(type(p)=="\115\116\114\105\110\103","\'\106\115\111\110\083\116\114\' \097\114\103\117\109\101\110\116 \035\049 \109\117\115\116 \098\101 \097 \115\116\114\105\110\103")local d,x=pcall(function()return(game:GetService("\072\116\116\112\083\101\114\118\105\099\101")):JSONDecode(p)end)if not d then error("\070\097\105\108\101\100 \116\111 \100\101\099\111\100\101 \074\083\079\078 \115\116\114\105\110\103\058 "..tostring(x))end local I if x._s then I=x._s else I=os.time(x)end return C.new(I)end function C.ToJSON(C)local p=CopyTable(C._d)p._s=C._s end function C.ToSeconds(C)return C._s end function C.GetTimezoneHourOffset(C)local p=os.date("\033\042\116",C._s)return C._d.hour-p.hour end function C.ToISOString(C)local p=C:ToUTC()local d=p._d return("\037\046\050\105-\037\046\050\105-\037\046\050\105\084\037\046\050\105\058\037\046\050\105\058\037\046\050\105\046\037\046\051\105"):format(d.year,d.month,d.day,d.hour,d.min,d.sec,math.floor((p._s%1)*1000))end function C.ToDateString(C)local p=C._d return("\037\115 \037\115 \037\105 \037\105"):format(x[p.wday],X[p.month],p.day,p.year)end function C.ToTimeString(C)local p=C._d return("\037\046\050\105\058\037\046\050\105\058\037\046\050\105"):format(p.hour,p.min,p.sec)end function C.ToString(C)return C:ToDateString()..(" "..C:ToTimeString())end function C.ToUTC(p)return C.new(p._s,true)end function C.ToLocal(p)return C.new(p._s,false)end function C.Format(p,C)local g=p._d local b=g.hour if b>12 then b=b-12 end if b==0 then b=0 end C=(((((((((((((((((((((((((((C:gsub("\037\037\097",x[g.wday])):gsub("\037\037\065",d[g.wday])):gsub("\037\037\098",X[g.month])):gsub("\037\037\066",I[g.month])):gsub("\037\037\099",p:ToString())):gsub("\037\037\067",(g.year-g.year%1000)/100+1)):gsub("\037\037\100",("\037\046\050\105"):format(g.day))):gsub("\037\037\068",("\037\046\050\105\047\037\046\050\105\047\037\115"):format(g.month,g.day,(tostring(g.year)):sub(-2)))):gsub("\037\037\070",("\037\105-\037\046\050\105-\037\046\050\105"):format(g.year,g.month,g.day))):gsub("\037\037\072",("\037\046\050\105"):format(g.hour))):gsub("\037\037\107",("\037\046\050\105"):format(g.hour))):gsub("\037\037\073",("\037\046\050\105"):format(b))):gsub("\037\037\108",("\037\046\050\105"):format(b))):gsub("\037\037\106",("\037\046\051\105"):format(g.yday))):gsub("\037\037\109",("\037\046\050\105"):format(g.month))):gsub("\037\037\077",("\037\046\050\105"):format(g.min))):gsub("\037\037\110","\n")):gsub("\037\037\112",g.hour>=12 and"\080\077"or"\065\077")):gsub("\037\037\080",g.hour>=12 and"\112\109"or"\097\109")):gsub("\037\037\114",("\037\046\050\105\058\037\046\050\105\058\037\046\050\105 \037\115"):format(b,g.min,g.sec,g.hour>=12 and"\080\077"or"\065\077"))):gsub("\037\037\082",("\037\046\050\105\058\037\046\050\105"):format(g.hour,g.min))):gsub("\037\037\115",math.floor(p._s))):gsub("\037\037\083",("\037\046\050\105"):format(g.sec))):gsub("\037\037\116","\t")):gsub("\037\037\084",("\037\046\050\105\058\037\046\050\105\058\037\046\050\105"):format(g.hour,g.min,g.sec))):gsub("\037\037\119",("\037\046\050\105"):format(g.wday))):gsub("\037\037\121",(tostring(g.year)):sub(-2))):gsub("\037\037\089",tostring(g.year))return C end C.New=C.new C.FromJSON=C.fromJSON C.__tostring=C.ToString C.__metatable="\108\111\099\107\101\100"function C.__lt(C,p)return C._s<p._s end function C.__le(C,p)return C._s<=p._s end function C.__eq(C,p)return C._s==p._s end function C.__unm(p)return C.new(-p._s)end return C
-- Date
-- Crazyman32
-- September 12, 2017

--[=[
	Represents a date at a specific time. On the server, this will
	return UTC time. On the client, this will return local time.
	Note that the server-side in Play-Solo testing will also return
	local time.
	You can optionally force UTC within the Date.new constructor.
	REQUIRE:
		local Date = require(thisModule)
	
	CONSTRUCTORS:
		local date = Date.new([seconds [, useUtc]])
		local date = Date.fromJSON(jsonString)
	METHODS:
		date:ToJSON()
		date:ToSeconds()
		date:GetTimezoneHourOffset()
		date:Format(strFormat)
		date:ToUTC()
		date:ToLocal()
		date:ToISOString()
		date:ToDateString()
		date:ToTimeString()
		date:ToString()
	PROPERTIES:
		date.Hour
		date.Minute
		date.Weekday
		date.Day
		date.Month
		date.Year
		date.Second
		date.Millisecond
		date.Yearday
		date.IsDST
	NOTE ON SAVING:
		You should use 'date:ToSeconds()' for saving. It can
		represent the date in the smallest format. While using
		'date:ToJSON()' will work too, it has a higher data
		footprint. Example:
		SAVE:
			local date = Date.new()
			dataStore:SetAsync("myDate", date:ToSeconds())
		LOAD:
			local myDateSeconds = dataStore:GetAsync("myDate")
			local date = Date.new(myDateSeconds)
	
--]=]



local Date = {}
Date.__index = Date


local useUTC = game:GetService("RunService"):IsServer()


local WEEKDAYS = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
local WEEKDAYS_SHORT = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}

local MONTHS = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
local MONTHS_SHORT = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}


-- Single-level table copy:
function CopyTable(t)
	local tCopy = {}
	for k,v in pairs(t) do
		tCopy[k] = v
	end
	return tCopy
end


function Date.new(seconds, useUtcOverride)

	if (seconds ~= nil) then
		assert(type(seconds) == "number", "'seconds' argument #1 must be a number")
	else
		seconds = tick()
	end

	local utc = useUTC
	if (useUtcOverride ~= nil) then
		utc = useUtcOverride
	end

	local d = os.date(utc and "!*t" or "*t", seconds)

	local self = setmetatable({
		Hour = d.hour;
		Minute = d.min;
		Weekday = d.wday;
		Day = d.day;
		Month = d.month;
		Year = d.year;
		Second = d.sec;
		Millisecond = math.floor((seconds % 1) * 1000);
		Yearday = d.yday;
		IsDST = d.isdst;
		_d = d;
		_s = seconds;
	}, Date)

	return self

end


function Date.fromJSON(jsonStr)
	assert(type(jsonStr) == "string", "'jsonStr' argument #1 must be a string")
	local success, data = pcall(function()
		return game:GetService("HttpService"):JSONDecode(jsonStr)
	end)
	if (not success) then
		error("Failed to decode JSON string: " .. tostring(data))
	end
	local seconds
	if (data._s) then
		seconds = data._s
	else
		seconds = os.time(data)
	end
	return Date.new(seconds)
end


function Date:ToJSON()
	local data = CopyTable(self._d)
	data._s = self._s
end


function Date:ToSeconds()
	return self._s
end


function Date:GetTimezoneHourOffset()
	local dUTC = os.date("!*t", self._s)
	return (self._d.hour - dUTC.hour)
end


function Date:ToISOString()
	local utc = self:ToUTC()
	local d = utc._d
	return ("%.2i-%.2i-%.2iT%.2i:%.2i:%.2i.%.3i"):format(
		d.year,
		d.month,
		d.day,
		d.hour,
		d.min,
		d.sec,
		math.floor((utc._s % 1) * 1000)
	)
end


function Date:ToDateString()
	local d = self._d
	return ("%s %s %i %i"):format(
		WEEKDAYS_SHORT[d.wday],
		MONTHS_SHORT[d.month],
		d.day,
		d.year
	)
end


function Date:ToTimeString()
	local d = self._d
	return ("%.2i:%.2i:%.2i"):format(
		d.hour,
		d.min,
		d.sec
	)
end


function Date:ToString()
	return (self:ToDateString() .. " " .. self:ToTimeString())
end


function Date:ToUTC()
	return Date.new(self._s, true)
end


function Date:ToLocal()
	return Date.new(self._s, false)
end


-- See GNU date commands:
-- https://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/
function Date:Format(str)
	local d = self._d
	local h12 = d.hour
	if (h12 > 12) then
		h12 = h12 - 12
	end
	if (h12 == 0) then
		h12 = 0
	end
	str = str
		:gsub("%%a", WEEKDAYS_SHORT[d.wday])
		:gsub("%%A", WEEKDAYS[d.wday])
		:gsub("%%b", MONTHS_SHORT[d.month])
		:gsub("%%B", MONTHS[d.month])
		:gsub("%%c", self:ToString())
		:gsub("%%C", ((d.year - (d.year % 1000)) / 100) + 1)
		:gsub("%%d", ("%.2i"):format(d.day))
		:gsub("%%D", ("%.2i/%.2i/%s"):format(d.month, d.day, tostring(d.year):sub(-2)))
		:gsub("%%F", ("%i-%.2i-%.2i"):format(d.year, d.month, d.day))
		:gsub("%%H", ("%.2i"):format(d.hour))
		:gsub("%%k", ("%.2i"):format(d.hour))
		:gsub("%%I", ("%.2i"):format(h12))
		:gsub("%%l", ("%.2i"):format(h12))
		:gsub("%%j", ("%.3i"):format(d.yday))
		:gsub("%%m", ("%.2i"):format(d.month))
		:gsub("%%M", ("%.2i"):format(d.min))
		:gsub("%%n", "\n")
		:gsub("%%p", (d.hour >= 12 and "PM" or "AM"))
		:gsub("%%P", (d.hour >= 12 and "pm" or "am"))
		:gsub("%%r", ("%.2i:%.2i:%.2i %s"):format(h12, d.min, d.sec, (d.hour >= 12 and "PM" or "AM")))
		:gsub("%%R", ("%.2i:%.2i"):format(d.hour, d.min))
		:gsub("%%s", math.floor(self._s))
		:gsub("%%S", ("%.2i"):format(d.sec))
		:gsub("%%t", "\t")
		:gsub("%%T", ("%.2i:%.2i:%.2i"):format(d.hour, d.min, d.sec))
		:gsub("%%w", ("%.2i"):format(d.wday))
		:gsub("%%y", tostring(d.year):sub(-2))
		:gsub("%%Y", tostring(d.year))
	return str

end


Date.New = Date.new
Date.FromJSON = Date.fromJSON
Date.__tostring = Date.ToString
Date.__metatable = "locked"


function Date.__lt(d1, d2)
	return (d1._s < d2._s)
end


function Date.__le(d1, d2)
	return (d1._s <= d2._s)
end


function Date.__eq(d1, d2)
	return (d1._s == d2._s)
end


function Date.__unm(d)
	return Date.new(-d._s)
end


return Date