Convert duration in seconds to hours and minutes and skip empty values

Use

.gsub(/\b0+(?:\B|\s[hm](?:\s|$))/, '')  See proof. Explanation -------------------------------------------------------------------------------- \b the boundary between a word char (\w) and something that is not a word char -------------------------------------------------------------------------------- 0+ '0' (1 or more times (matching the most amount possible)) -------------------------------------------------------------------------------- (?: group, but do not capture: -------------------------------------------------------------------------------- \B the boundary between two word chars (\w) or two non-word chars (\W) -------------------------------------------------------------------------------- | OR -------------------------------------------------------------------------------- \s whitespace (\n, \r, \t, \f, and " ") -------------------------------------------------------------------------------- [hm] any character of: 'h', 'm' -------------------------------------------------------------------------------- (?: group, but do not capture: -------------------------------------------------------------------------------- \s whitespace (\n, \r, \t, \f, and " ") -------------------------------------------------------------------------------- | OR --------------------------------------------------------------------------------$                        before an optional \n, and the end of
the string
--------------------------------------------------------------------------------
)                        end of grouping
--------------------------------------------------------------------------------
)                        end of grouping


Why not just something simple like this:

def to_hms(time)
hours = time / 3600
minutes = (time / 60) % 60

if (hours > 0 and minutes > 0)
'%d h %d m' % [ hours, minutes ]
elsif (hours > 0)
'%d h' % hours
elsif (minutes > 0)
'%d m' % minutes
end
end


Where this produces the desired results:

to_hms(63000)
# => "17 h 30 m"
to_hms(28800)
# => "8 h"
to_hms(1800)
# => "30 m"


You can either match 00 followed by h or m, or you can match a 0 and assert a digit 1-9 directly to the right followed by either h or m

\b(?:00 [hm]|0(?=[1-9] [hm]))\s*


Rubular demo and a Ruby demo.

Time.at(duration1).utc.strftime('%H h %M m').gsub(/\b(?:00 [hm]|0(?=[1-9] [hm]))\s*/, ''))