Get hours, seconds and time from Date.day_fraction_to_time

  start = DateTime.now
  sleep 15
  stop = DateTime.now
  #minutes
  puts ((stop-start) * 24 * 60).to_i

  hours,minutes,seconds,frac = Date.day_fraction_to_time(stop-start)

I have the following error:

`<main>': private method `day_fraction_to_time' called for

Date:Class (NoMethodError)

I’ve checked /usr/lib/ruby/1.9.1/date.rb and I’ve found it:

def day_fraction_to_time(fr) # :nodoc:
  ss,  fr = fr.divmod(SECONDS_IN_DAY) # 4p
  h,   ss = ss.divmod(3600)
  min, s  = ss.divmod(60)
  return h, min, s, fr * 86400
end

But I have no problem if I run it with ruby1.8.
/usr/lib/ruby/1.8/date.rb gives me:

  def self.day_fraction_to_time(fr)
    ss,  fr = fr.divmod(SECONDS_IN_DAY) # 4p
    h,   ss = ss.divmod(3600)
    min, s  = ss.divmod(60)
    return h, min, s, fr
  end

So I went to see the documentation(1.9)1 and there’s no trace of this
method. I know it’s a dumb question, but why did they remove it? There
is even this example on how to use the method in
/usr/lib/ruby/1.9.1/date.rb:

 def secs_to_new_year(now = DateTime::now())
     new_year = DateTime.new(now.year + 1, 1, 1)
     dif = new_year - now
     hours, mins, secs, ignore_fractions =

Date::day_fraction_to_time(dif)
return hours * 60 * 60 + mins * 60 + secs
end

but I’m still getting the error:

test.rb:24:in `secs_to_new_year': private method

day_fraction_to_time' called for Date:Class (NoMethodError) from test.rb:28:in

See below at *** for two “work-arounds” which seem to allow you to do
what
you want in Ruby 1.9 as well as in 1.8.6 and 1.8.7.

Some links for explanations of private and public (and protected)
methods:
http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby
Here (for example) under Access Control:
http://ruby-doc.org/docs/ProgrammingRuby/html/tut_classes.html

Private methods cannot be called with an explicit receiver. Because you
cannot specify an object when using them, private methods can be called
only
in the defining class and by direct descendents within that same object.

Compare the “full” code for the 1.8 and 1.9 versions of Date. (See just
below.) The 1.8 version can only be used as a class method
Date.day_fraction_to_time, but the 1.9 version can also be used as a
private instance method.

That said, I don’t know why the class (singleton) method
day_fraction_to_time was changed from public in Date before 1.9 to
private
in 1.9, and I would welcome any enlightened suggestions. (One reason for
making a method private is, I assume, to warn people that an internal
implementation detail might change, so it would be unwise to use such a
private method in case its implementation changes in the future. That
gives
more freedom to the code originator for future changes.)

In 1.8:

class Date
#…
def self.day_fraction_to_time(fr)
#…
end
#…
end

But in 1.9:

class Date
#…
t = Module.new do
private
#…
def day_fraction_to_time(fr) # :nodoc:
#…
end
#…
end
extend t
include t
#…
end

*** work arounds

require “date”

start = DateTime.now
sleep 3
stop = DateTime.now

minutes

puts( ((stop - start) * 24 * 60).to_i )

puts “Date.day_fraction_to_time”
begin
hours, minutes, seconds, frac =
Date.day_fraction_to_time( stop - start ) # works in 1.8.6 & 1.8.7
p hours, minutes, seconds, frac
rescue # raises exception in 1.9.1
p $!
end

puts “Date.day_fraction_to_time using send
hours, minutes, seconds, frac =
Date.send( :day_fraction_to_time, stop - start )
p hours, minutes, seconds, frac

puts “Date.day_fraction_to_time using wrapper”
class Date
class << self
def wrap_day_fraction_to_time( day_frac )
day_fraction_to_time( day_frac )
end
end
end
hours, minutes, seconds, frac =
Date.wrap_day_fraction_to_time( stop - start )
p hours, minutes, seconds, frac

Colin B. wrote:

puts “Date.day_fraction_to_time using wrapper”
class Date
class << self
def wrap_day_fraction_to_time( day_frac )
day_fraction_to_time( day_frac )
end
end
end
hours, minutes, seconds, frac =
Date.wrap_day_fraction_to_time( stop - start )
p hours, minutes, seconds, frac

Thanks for the answer. Could you examplain me the wrapper in detail,
please? I’m assuming you’re extending the Date class with an anonymous
class but it’s really not clear to me the class << self declaration.

On Sat, Sep 18, 2010 at 12:09 PM, Emanuele I. [email protected]
wrote:

Date.wrap_day_fraction_to_time( stop - start )

p hours, minutes, seconds, frac

Thanks for the answer. Could you explain me the wrapper in detail,
please? I’m assuming you’re extending the Date class with an anonymous
class but it’s really not clear to me the class << self declaration.

I’m not surprised that “class << self” isn’t clear to you. It wasn’t
clear
to me when I first saw it, and I’m not sure I’m 100% there yet! I hope
the
following is right and helps. (Corrections are welcome.)

Here’s a link to the online first edition of Programming Ruby
http://ruby-doc.org/docs/ProgrammingRuby/html/classes.html
… Object-Specific Classes …

Basically you can extend any object with methods which won’t be
available to
any other object unless you also extend that other object.

In the version of Date with Ruby 1.9 one way used is to set up an
(anonymous?) module and then use “extend”, as shown in the extract from
(1.9) Date in my first post in this thread.

Another way is to use the “class << object” notation, which (I think)
says
evaluate the code in “class<<…end” in the context of the specified
object,
extending that object (as singleton methods of that object) with any
methods
defined in “class<<…end”. For example:
obj = Array.new
(r = obj.new_singleton_method) rescue p $! #=> undefined method error
class << obj
def new_singleton_method(); “Karel Capek”; end
end
r = obj.new_singleton_method #=> “Karel Capek”

So in:
class Date
class << self
def wrap_day_fraction_to_time( day_frac )
day_fraction_to_time( day_frac )
end
end
end
the object being extended in “class<<self…end” is whatever “self” is,
and
in the context of the “class Date” self is the Date class. And the
private
method “day_fraction_to_time” is accessible from “within” the object, so
we
can write a public method (callable as Date.wrap_day_fraction_to_time)
which
calls the private method “day_fraction_to_time”.

Also, instead of writing a wrapper method, the following (simpler) way
also
seems to work:
hours = mins = secs = nil
hours, mins, secs = Date.day_fraction_to_time( 0.03125 ) rescue p $!
p hours, mins, secs #=> nil, nil, nil
class Date
class << self
public :day_fraction_to_time
end
end
hours, mins, secs = Date.day_fraction_to_time( 0.03125 ) rescue p $!
p hours, mins, secs #=> 0, 45, 0

In the context of a private method, I’m not at all sure that putting a
public wrapper method which calls it is better than simply making the
private method public: I think that any downsides/problems with making
the
private method public will also apply to wrapping it. Does anyone know
(or
think) differently?