--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] -- Copyright © 2022-2072, Nak, https://steamcommunity.com/id/Nak2/ -- All Rights Reserved. Not allowed to be reuploaded. -- License: https://github.com/Nak2/NikNaks/blob/main/LICENSE --- @class TimeDelta --- @operator add:TimeDelta|DateTime --- @operator sub:TimeDelta|DateTime --- @operator mul:TimeDelta --- @operator div:TimeDelta --- @operator pow:TimeDelta --- @operator mod:TimeDelta local meta = {} meta.__index = meta meta.MetaName = "TimeDelta" NikNaks.__metatables["TimeDelta"] = meta --- @class TimeDeltaModule --- @operator call:TimeDelta local TimeDelta = {} TimeDelta.Milisecond = 0.001 TimeDelta.Second = 1 TimeDelta.Minute = 60 TimeDelta.Hour = 3600 TimeDelta.Day = 86400 TimeDelta.Week = 604800 TimeDelta.Year = 31536000 TimeDelta.Decade = 315359654 TimeDelta.Century = 3153596543 TimeDelta._steps = { "Year", "Day", "Hour", "Minute", "Second", "Milisecond" } setmetatable( TimeDelta, { __index = TimeDelta, __call = function( _, time ) return setmetatable( { time = time }, meta ) end } ) NikNaks.TimeDelta = TimeDelta do local abs = math.abs local floor = math.floor local steps = TimeDelta._steps --- Returns the time as a table --- @return table function meta:ToTable() if self._tab then return self._tab end local t = {} local num = abs( self.time ) local f = self.time < 0 and -1 or 1 local isLeapYear = NikNaks.DateTime.IsLeapYear local function processStep( i ) local step = steps[i] local value = steps[step] -- Leap year if num < value then return end if i == 1 then -- Since years aren't whole numbers, we need to round the tiniest amount, or floor is going to count down. local n = 0 local y = TimeDelta.Year local v = isLeapYear( y ) and 31622400 or 31536000 while num >= v do local q = 1 * f if num >= v then n = n + 1 num = num - v y = y + q v = isLeapYear( y ) and 31622400 or 31536000 else break end end t[s] = n * f else local n = floor( num / v ) t[s] = n * f num = num - v * n end end for i = 1, #steps do processStep( i ) end self._tab = t return t end end -- Getters do --- Generic getter function to get the time amount of the given time type --- @param key string The name of the time type to get --- @return number function meta:_getter( key ) return self.time / TimeDelta[key] end function meta:GetMiliseconds() return self:_getter( "Milisecond" ) end function meta:GetSeconds() return self:_getter( "Second" ) end function meta:GetMinutes() return self:_getter( "Minute" ) end function meta:GetHours() return self:_getter( "Hour" ) end function meta:GetDays() return self:_getter( "Day" ) end function meta:GetWeeks() return self:_getter( "Week" ) end function meta:GetMonths() return self:_getter( "Month" ) end function meta:GetYears() return self:_getter( "Year" ) end function meta:GetDecades() return self:_getter( "Decade" ) end function meta:GetCenturies() return self:_getter( "Century" ) end end -- Adders do --- Generic adder function to add given time amount to the TimeDelta --- @param key string The name of the time type to add --- @param num number The amount of time to add --- @return self TimeDelta function meta:_adder( key, num ) self.time = self.time + ( num * TimeDelta[key] ) self._tab = nil return self end --- @param n number function meta:AddMiliseconds( n ) return self:_adder( "Milisecond", n ) end --- @param n number function meta:AddSeconds( n ) return self:_adder( "Second", n ) end --- @param n number function meta:AddMinutes( n ) return self:_adder( "Minute", n ) end --- @param n number function meta:AddHours( n ) return self:_adder( "Hour", n ) end --- @param n number function meta:AddDays( n ) return self:_adder( "Day", n ) end --- @param n number function meta:AddWeeks( n ) return self:_adder( "Week", n ) end --- @param n number function meta:AddMonths( n ) return self:_adder( "Month", n ) end --- @param n number function meta:AddYears( n ) return self:_adder( "Year", n ) end --- @param n number function meta:AddDecades( n ) return self:_adder( "Decade", n ) end --- @param n number function meta:AddCenturies( n ) return self:_adder( "Century", n ) end --- @param n number end -- Subtractors do --- Generic subtractor function to subtract given time amount from the TimeDelta --- @param key string The name of the time type to subtract --- @param num number The amount of time to subtract --- @return self TimeDelta function meta:_subtractor( key, num ) self.time = self.time - ( num * TimeDelta[key] ) self._tab = nil return self end function meta:SubMiliseconds( n ) return self:_subtractor( "Milisecond", n ) end --- @param n number function meta:SubSeconds( n ) return self:_subtractor( "Second", n ) end --- @param n number function meta:SubMinutes( n ) return self:_subtractor( "Minute", n ) end --- @param n number function meta:SubHours( n ) return self:_subtractor( "Hour", n ) end --- @param n number function meta:SubDays( n ) return self:_subtractor( "Day", n ) end --- @param n number function meta:SubWeeks( n ) return self:_subtractor( "Week", n ) end --- @param n number function meta:SubMonths( n ) return self:_subtractor( "Month", n ) end --- @param n number function meta:SubYears( n ) return self:_subtractor( "Year", n ) end --- @param n number function meta:SubDecades( n ) return self:_subtractor( "Decade", n ) end --- @param n number function meta:SubCenturies( n ) return self:_subtractor( "Century", n ) end --- @param n number end -- ToString do local abs = math.abs local steps = TimeDelta._steps function meta:__tostring() local str local si = 0 local tab = self:ToTable() local kv = #table.GetKeys( tab ) for i = 1, #steps do local step = steps[i] if tab[step] then si = si + 1 local number = abs( tab[step] ) local middle = ( si == kv and " and " or ", " ) step = number == 1 and step or step .. "s" if not str then str = number .. " " .. step else str = str .. middle .. number .. " " .. step end end end return str or "nil" end end function meta:IsNegative() return self.time < 0 end function meta:IsPositive() return self.time >= 0 end -- Operations do --- @param b TimeDelta|number --- @return TimeDelta|DateTime function meta:__add( b ) if isnumber( b ) then return TimeDelta( self.time + b ) end if self.unix and b.time then return NikNaks.DateTime( self.unix + b.time ) elseif b.unix and self.time then return NikNaks.DateTime( b.unix + self.time ) end end --- @param b TimeDelta|number --- @return TimeDelta|DateTime function meta:__sub( b ) if isnumber( b ) then return TimeDelta( self.time - b ) end if self.unix and b.time then return NikNaks.DateTime( self.unix - b.time ) elseif b.unix and self.time then return NikNaks.DateTime( b.unix - self.time ) end end --- @param b TimeDelta|number --- @return TimeDelta function meta:__mul( b ) b = isnumber( b ) and b or b.time return TimeDelta( self.time * b ) end --- @param b TimeDelta|number --- @return TimeDelta function meta:__div( b ) b = isnumber( b ) and b or b.time return TimeDelta( self.time / b ) end --- @param b TimeDelta|number --- @return TimeDelta function meta:__pow( b ) b = isnumber( b ) and b or b.time return TimeDelta( self.time ^ b ) end --- @param b TimeDelta|number --- @return TimeDelta function meta:__mod( b ) b = isnumber( b ) and b or b.time return TimeDelta( self.time % b ) end --- @param b TimeDelta function meta:__eq( b ) return self.time == b.time end --- @param b TimeDelta function meta:__lt( b ) return a.time < b.time end --- @param b TimeDelta function meta.__le( b ) return a.time <= b.time end end