How can I format this time formatting script more compact?

I am working on a game and I wanted to implement a ‘time since joined’ system to the game, I got everything working but I feel like I could format the formatting system better. I’ve looked into it and couldn’t find any resources relevant enough to what I’m trying to do.

	val = math.floor(val+0.5)
	local Seconds = val % 60
	local Minutes = math.floor(val / 60) % 60
	local Hours = math.floor(val / 3600) % 24
	local Days = math.floor(val / 86400) % 7
	local Weeks = math.floor(val / 604800)
	if Weeks > 0 then
		if Days > 0 then
			return Weeks.." week"..(Weeks>1 and "s" or "").." and "..Days.." day"..(Days>1 and "s" or "")
		else
			return Weeks.." week"..(Weeks>1 and "s" or "")
		end		
	elseif Days > 0 then
		if Hours > 0 then
			return Days.." day"..(Days>1 and "s" or "").." and "..Hours.." day"..(Hours>1 and "s" or "")
		else
			return Days.." day"..(Days>1 and "s" or "")
		end		
	elseif Hours > 0 then
		if Minutes > 0 then
			return Hours.." hour"..(Hours>1 and "s" or "").." and "..Minutes.." minute"..(Minutes>1 and "s" or "")
		else
			return Hours.." hour"..(Hours>1 and "s" or "")
		end		
	elseif Minutes > 0 then
		if Seconds > 0 then
			return Minutes.." minute"..(Minutes>1 and "s" or "").." and "..Seconds.." second"..(Seconds>1 and "s" or "")
		else
			return Minutes.." minute"..(Minutes>1 and "s" or "")
		end		
	else
		return Seconds .. " second"..(Seconds>1 and "s" or "")
	end

Is there anyway I could make this script shorter and not need all the if and elseif statements?
Should I leave it the way it is?

Just append each larger unit to the start of the output string if its greater than zero.

How would I go about doing that?

Do you want there to be “zero” of anything in between the largest and smallest unit? Like 1 Week 0 Days 3 Hours etc?

No I want it so it’ll only show the two highest units above 0
For example:
1 week and 2 days,
5 hours and 29 minutes
But if the unit below the highest unit is 0 then it’ll be just the highest unit:
1 day
5 hours

I kind of figured it out with this

	val = math.floor(val+0.5)
	local Seconds = val % 60
	local Minutes = math.floor(val / 60) % 60
	local Hours = math.floor(val / 3600) % 24
	local Days = math.floor(val / 86400) % 7
	local Weeks = math.floor(val / 604800)
	return(Weeks>0 and (Weeks.." week" .. (Weeks>1 and "s" or "") or "") or "")
	.. (Weeks>0 and Days>0 and " and " or "") 
	.. (Days>0 and (Days.." day" .. (Days>1 and "s" or "") or "") or "")
	.. (Weeks==0 and Days>0 and Hours>0 and " and " or "") 
	.. (Weeks==0 and Hours>0 and (Hours.." hour" .. (Hours>1 and "s" or "") or "") or "")
	.. (Weeks==0 and Days==0 and Hours>0 and Minutes>0 and " and " or "") 
	.. (Weeks==0 and Days==0 and Minutes>0 and (Minutes.." minute" .. (Minutes>1 and "s" or "") or "") or "")
	.. (Weeks==0 and Days==0 and Hours==0 and Minutes>0 and Seconds>0 and " and " or "") 
	.. (Weeks==0 and Days==0 and Hours==0 and Seconds>0 and (Seconds.." second" .. (Seconds>1 and "s" or "") or "") or "")

I still don’t know if this is the most efficient way but I’ll stick with it.

I use a loop; it looks something like this: (You can also change the amount off values returned)

local timeNames = {"week", "day", "hour", "minute", "second"}

local function strinigfyTime(seconds : number, maxSteps : number?)
	if tonumber(maxSteps) == nil or 2 > tonumber(maxSteps) then
		maxSteps = 2
	else
		maxSteps = math.floor(maxSteps)
	end
	
	seconds = math.floor(math.abs(seconds) + 0.5)
	
	local Seconds = seconds % 60
	local Minutes = math.floor(seconds/60) % 60
	local Hours = math.floor(seconds/3600) % 24
	local Days = math.floor(seconds/86400) % 7
	local Weeks = math.floor(seconds/604800)
	
	local hierarchy = {Weeks, Days, Hours, Minutes, Seconds}
	local stepped = 0
	local output = ""
	
	for i, time_ in ipairs(hierarchy) do
		if time_ == 0 then
			if stepped == maxSteps - 1 then
				break
			end
			
			continue
		end
		
		if stepped == maxSteps - 1 then
			output = output .. " and" .. (maxSteps > 2 and ", " or " ") .. time_ .. " " .. timeNames[i] .. (time_ > 1 and "s" or "")
			break
		end
		
		if stepped == 0 then
			output = output .. time_ .. " " .. timeNames[i] .. (time_ > 1 and "s" or "")
		else
			output = output .. ", " .. time_ .. " " .. timeNames[i] .. (time_ > 1 and "s" or "")
		end
		
		stepped += 1
	end
	
	return output
end

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.