Lua formatting returns unexpected results

I recently wrote a small program where I'm trying to convert a number of seconds into a more human readable format, but I'm having problems when trying to format the output and somehow I end up getting unexpected output. Here is the code

local minutes, hours = 60, 3600
local s = 5400

-- output is 2h30m when it should be 1h30m
if s >= hours then
    print(string.format("%.0fh%.0fm", s / hours, (s % hours) / minutes))

-- output is 45m0s when it should be 45m
if s >= minutes then
    print(string.format("%.0fm%.0fs", s / minutes, s % minutes))

Even though the amount of seconds (s) is 5400 which is 1 hour and 30 minutes, the first if-statement will ouput 2h30m which is one hour more, whereas the second if-statement prints the correct 90m. If y'all could help me with some ideas or point me in the right direction, I'd be extremely grateful! Have a good one!


  • The problem stems from the fact that %.0f does not truncate: It rounds. print(("%.0f"):format(1.5)) prints 2, not 1. This is exactly the case here: You have 1h30m, or 1.5h (the "edge case"). This gets rounded up to two hours by %.0f. What you really want instead is floor division. Simply wrap the division in a math.floor; then you can use %d for integer formatting as well:

    print(string.format("%dh%dm", math.floor(s / hours), math.floor((s % hours) / minutes))) -- 1h30m as expected

    The second if suffers from the same issue. You should also use a math.floor there. I'm not sure why you expect the 0s to be omitted, given that there is no code for it. You'd have to implement that using another if.