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 `<main>'
[1]: http://ruby-doc.org/core-1.9/classes/Date.html
on 2010-09-17 11:25
on 2010-09-18 04:04
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-visib... Here (for example) under Access Control: http://ruby-doc.org/docs/ProgrammingRuby/html/tut_... ... 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
on 2010-09-18 13:08
Colin Bartlett 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 2010-09-19 20:25
On Sat, Sep 18, 2010 at 12:09 PM, Emanuele Ianni <dierre@gmail.com> 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?
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.