Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

regex

ruby

We have a Time Tracking model with a duration (in seconds) value that is always greater than 60 (1 minute).

I need to convert the duration to hours and minutes if they are not zero and without zero at the start of hours or minutes. For example:

duration1 = 63000  # expected value:  17 h 30 m
duration2 = 28800  # expected value:  8 h
duration3 = 1800   # expected value:  30 m
duration4 = 300    # expected value:  5 m

I almost did, but have small problem with a zero values:

Time.at(duration1).utc.strftime('%H h %M m').sub!(/^0/, '') 
# 17 h 30 m

Time.at(duration2).utc.strftime('%H h %M m').sub!(/^0/, '') 
# 8 h 00 m

Time.at(duration3).utc.strftime('%H h %M m').sub!(/^0/, '') 
# 0 h 30 m

Time.at(duration4).utc.strftime('%H h %M m').sub!(/^0/, '') 
# 0 h 05 m

Thanks for answers.

like image 473
Roman Avatar asked Feb 09 '21 22:02

Roman


People also ask

How do you convert seconds to HH MM SS?

Find the number of whole hours by dividing the number of seconds by 3,600. The number to the left of the decimal point is the number of whole hours. The number to the right of the decimal point is the number of partial hours.


2 Answers

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"
like image 69
tadman Avatar answered Nov 11 '22 21:11

tadman


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
like image 37
Ryszard Czech Avatar answered Nov 11 '22 21:11

Ryszard Czech