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*/, ''))

Tags:

Ruby

Regex