tags:

views:

312

answers:

1

I'm trying to make a time with Time.local which in my code is dynamic. On the first of each month the values I'm passing are Time.local(2009, 9, -1, 0). In PHP this would set the time to the last day of the previous month. In ruby I just get "ArgumentError: argument out of range".

Am I using the wrong method or something? Thanks.

+3  A: 

You should use the DateTime class instead of Time. (You might have to require 'date' and install the activesupport gem first.)

It is much more versatile than Time and does just what you want with DateTime.civil(2009,9 - 1,-1,0).

Passing -1 for the day gives you the date of the last day of the month from the second argument, so you have to subtract 1 from the current month.

If you are in Rails, you could just do DateTime.civil(2009,9,1,0) - 1.day and get what you want with more understandable code.

mrueg
But this sets the date to the last day of the current month, doesn't it?
jgre
Yes it does:>> DateTime.civil(2009,9,-1)=> Wed, 30 Sep 2009 00:00:00 +0000Almost had it!
sebastyuiop
Ah yes, made a small mistake there. Will edit my original answer.
mrueg
Nice one, that works a treat. I'll vote it up when I get to 15 rep! Thanks
sebastyuiop
Also note that with ActiveSupport (included in Rails but can be used standalone) you have #end_of_month which does exactly what you'd expect (for reasonable values of "expect"). See ActiveSupport::CoreExtensions::Date::Calculations for other useful bits.
Mike Woodhouse
I'd also note that if this is a calculation you're going to be making frequently, Ruby's DateTime class is much, much slower than its Time class. (Time is mostly written in C, whereas DateTime is pure Ruby and makes heavy use of Rational). DateTime is more fully featured, however. (http://third-base.rubyforge.org is an alternative DateTime implementation which claims to be quite a bit faster)
Greg Campbell