richard
richard

Reputation: 1585

Timecodes in Rails - time or numeric values?

I'm working on a project that stores data on audio tracks and requires the use of timecodes for the start and end points of the track on the audio. I also need to calculate and display the duration of the track. Eg. a track starts at 0:01:30 and finishes at 0:04:12. So its duration is a total of 2 mins and 42 secs.

The trick is that everything needs to be displayed and handled as timecodes, so in the above example the duration needs to be displayed as 0:02:42.

So my question is how you would store the values? The easiest option would be to store the start and end times as Time in the database. Its very easy to calculate the duration and you can utilise the Rails time helpers in the forms. The only painful part is turning the duration back into a time value for display (since if I supply just the number of seconds to strptime it keeps using the current time to fill in the other fields)

The other option that I considered is storing them as numeric values (as the number of seconds). But then I have to write a lot of code to convert them to and from some type of timecode format and I can't use the Rails time helpers.

Is there another idea that I haven't considered? Is there an easy way to calculate and display the duration as a timecode format?

Upvotes: 3

Views: 695

Answers (1)

Paige Ruten
Paige Ruten

Reputation: 176803

I would store them as seconds or milliseconds. I've been working on a music library manager/audio player in Ruby, and I actually had to write the two methods you would need. It's not that much code:

  # Helper method to format a number of milliseconds as a string like
  # "1:03:56.555". The only option is :include_milliseconds, true by default. If
  # false, milliseconds won't be included in the formatted string.
  def format_time(milliseconds, options = {})
    ms = milliseconds % 1000
    seconds = (milliseconds / 1000) % 60
    minutes = (milliseconds / 60000) % 60
    hours = milliseconds / 3600000

    if ms.zero? || options[:include_milliseconds] == false
      ms_string = ""
    else
      ms_string = ".%03d" % [ms]
    end

    if hours > 0
      "%d:%02d:%02d%s" % [hours, minutes, seconds, ms_string]
    else
      "%d:%02d%s" % [minutes, seconds, ms_string]
    end
  end

  # Helper method to parse a string like "1:03:56.555" and return the number of
  # milliseconds that time length represents.
  def parse_time(string)
    parts = string.split(":").map(&:to_f)
    parts = [0] + parts if parts.length == 2
    hours, minutes, seconds = parts
    seconds = hours * 3600 + minutes * 60 + seconds
    milliseconds = seconds * 1000
    milliseconds.to_i
  end

It's written for milliseconds, and would be a lot simpler if it was changed to work with seconds.

Upvotes: 4

Related Questions