Off Topic Advice Needed (Time objects)

I know this is a Ruby question but I’m not on any Ruby mailing lists and it’s for a Rails project (so might come under select_time etc. :wink: ) I thought I’d try here.

A user can choose integer values from select drop down boxes to predict how long an event will take. Obvious values are secs (0-59), minutes (0-59) … weeks (0-4), months (0-11) …

These values are then converted to seconds and stored as decimal in the DB (I allow fractions of a second, too (tenth, hundredth, millisecond). when they are retrieved form the DB, I convert the seconds to a string format of, for example, 01:39:11 (from 5951 seconds). If fractions are used, they are just appended to the string. (non of this is elegant IMO)

That’s all done in my Converter class. I am going to write a Calculator class to compare all times entered for an event and picking the closest times to how long the actual event took.

So my question is, I know I can’t use a Time object but it would be really nice to know if there is something out there that could help me with this as to write my own Calculator is going to be a bit of a pain.

Also, by throwing this out there, somebody might say something that I haven’t thought of doing and could totally change the way I’m doing this.

CIA

-Ants

These values are then converted to seconds and stored as decimal in the DB (I allow fractions of a second, too (tenth, hundredth, millisecond). when they are retrieved form the DB, I convert the seconds to a string format of, for example, 01:39:11 (from 5951 seconds). If fractions are used, they are just appended to the string. (non of this is elegant IMO)

That’s all done in my Converter class. I am going to write a Calculator class to compare all times entered for an event and picking the closest times to how long the actual event took.

So my question is, I know I can’t use a Time object but it would be really nice to know if there is something out there that could help me with this as to write my own Calculator is going to be a bit of a pain.

If you have two floating point values representing seconds (and parts of) why can’t you just compare the two floating point values?

What part are you stuck with? Can you give us some code with a comment on which bit you can’t do.

Andy

I don’t have a problem with comparing floats, but I might need to find the 10 closest times to the actual event time and 4 of those times could be less than the actual event time and 6 could be higher.

I don’t mind rolling my own and am quite looking forward to it, but I don’t want to re-invent the proverbial wheel.

FWIW, here’s the conversion code to convert integer values to their respective seconds.

@@time_constants = {:years => YEAR,
  :months => MONTH,
  :weeks => WEEK,
  :days => DAY,
  :hours => HOUR,
  :mins => MIN  }

def to_decimal(time_units={})

  raise ArgumentError if time_units.empty?

  time_units.each_pair do |key, value|
    ## skip seconds and fractions thereof
    next unless @@time_constants.has_key?(key)
    ## convert integer time units into seconds

    @decimal_time += @@time_constants[key] * value
  end
  ## whack on the seconds
  @decimal_time += time_units[:secs] if time_units.has_key?(:secs)

  ## need validation (can't have hundtedth without tenth, for example)

  fraction = ''
  fraction = '.' + time_units[:tenth].to_s      if time_units.has_key?(:tenth)
  fraction << time_units[:hundredth].to_s   if time_units.has_key?(:hundredth)
  fraction << time_units[:millisecond].to_s if time_units.has_key?(:millisecond)

  ## concat fraction string to @decimal_time, convert to float for DB
  @decimal_time = (@decimal_time.to_s << fraction).to_f
end

If you have two floating point values representing seconds (and parts of) why can’t you just compare the two floating point values?

What part are you stuck with? Can you give us some code with a comment on which bit you can’t do.

I don’t have a problem with comparing floats, but I might need to find the 10 closest times to the actual event time and 4 of those times could be less than the actual event time and 6 could be higher.

I don’t mind rolling my own and am quite looking forward to it, but I don’t want to re-invent the proverbial wheel.

This seems a fairly simple wheel to be worried about re-inventing though (or even to look forward to).

OK, so you have an array of times. You sort through them based on:

(predicted_time - actual_time).abs

and pick the smallest 10 items.

Cheers,

Andy

As a starting point, IIWM I would:
  * Get the ten times either side (so I have twenty objects).
  * Calculate the difference of how far each is from the event (ignoring sign)
  * Order the twenty by the difference
  * Take the first ten of them.

With a bit of thought this could all be done in SQL... possibly with a
couple of sub-queries. But it could certainly be stepped through in
Ruby very easily.

As I have said before, I have no problems with all of that but thanks for the suggestions. Things do get a bit more complicated with the Calculator, though and I was only looking to make sure I wasn’t wasting my time when there was something already out there.

I’ll just press on. Again, thanks for your time.

To be honest, I don't really understand what you're asking for help
with. If you can state your position in different terms, because what
you've said so far obviously hasn't clicked with anyone (or at least
we've clicked the same, wrong, way! :wink:

Feeling around in the dark a little:
http://snippets.dzone.com/posts/show/1137
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/170729

The code you posted does look a little smelly. I don't know why you're
turning your numbers into strings and then back into numbers again.
For instance, where you say " ## need validation (can't have hundtedth
without tenth, for example)", I think you could ignore if you just
approach adding up the seconds differently.

So for instance if :
   time_units = {:seconds => 22, :hundredths => 0, :milliseconds => 8}

you can just do the arithmetic:

  fraction = 0
  fraction += time_units[:tenths] * .1 if time_units.has_key?(:tenths)
  fraction += time_units[:hundredths] * .01 if time_units.has_key?(:hundredths)
  fraction += time_units[:milliseconds] *.001 if
time_units.has_key?(:milliseconds)

should result in 0.008

Frankly, stuff the fraction variable. Treat @decimal_time the same:
  @decimal_time += time_units[:seconds] if time_units.has_key?(:seconds)
  @decimal_time += time_units[:minutes] * 60 if time_units.has_key?(:minutes)
  @decimal_time += time_units[:hours] * 3600 if time_units.has_key?(:hours)
  @decimal_time += time_units[:milliseconds] *.001 if
time_units.has_key?(:milliseconds)
  etc...

Of course, ignore me if there's some critical reason they *must* be strings! :slight_smile:

Not to worry about this as I’m happy where I’m going. Logically it’s not a huge problem, getting it Rubyish might be :wink: Long time Perl programmer.

Thanks for the links, I’d already seen the second link.

Thanks for the bit about the fractions, it’s given me something to think about but from what I can see, they will still have to be tacked on to the decimal. The decimals were done the way you suggested but now they’re just in a loop (more flexible) as time_units may well be added in the future.

I don’t want to labour on this so I’ll just do what I was going to do. Again, thanks.

Ants Pants wrote:

I know this is a Ruby question but I'm not on any Ruby mailing lists

Then get on one (perhaps ruby-talk) and ask there. Don't make lazy
excuses for asking off-topic questions.

and
it's for a Rails project (so might come under select_time etc. :wink: )

That may be a better reason to ask here.

I
thought I'd try here.

I'll look at your question when I have a little more time, but please
remember that "because I couldn't bother to join the appropriate list"
is not a valid reason for posting off-topic questions. :slight_smile:

Best,