keoghpe
keoghpe

Reputation: 404

Ruby loses millisecond somewhere

I'm trying to add milliseconds for some timestamps. It seems that there are some milliseconds getting lost somewhere.

input:    00:00:36,040
expected: 00:00:37,040
output:   00:00:37,039

Any ideas?

puts Timestamp.new("00:00:36,040").add("1,000").to_string

class Timestamp

  def initialize(instr)
     h, m, s, l = instr.split(/[:,]/).map { |x| x.to_i }
     @time = Time.at(h*3600 + m*60 + s + l*0.001 ) - Time.new.utc_offset
  end

  def to_string
    @time.strftime("%H:%M:%S,%L")
  end
end

Upvotes: 0

Views: 116

Answers (1)

Schwern
Schwern

Reputation: 165416

You are likely being caught by one of the oldest problems in computing, floating point inaccuracies.

$ ruby -e 'puts 3723.004.class'
Float

$ ruby -e 'puts Time.at(3723.004).strftime("%H:%M:%S,%L")'
17:02:03,003

Simply put, numbers like 3723.004 are not what they seem. Computers store them very differently and it results in slight inaccuracies in odd places. These inaccuracies can add up in calculations.

To work around this, stick to integers where possible. Use the two argument form of Time.at (note: it takes microseconds).

$ ruby -e 'puts Time.at(3723, 4000).strftime("%H:%M:%S,%L")'
17:02:03,004

Upvotes: 4

Related Questions