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. ) 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.
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.
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
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.
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.
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 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.
As I have said before, I have no problems with all of that but thanks for
the suggestions.
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!
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!
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. )
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.