Forum: Ruby [newbie] this month, the next month, and the one after that

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Fb8f512d95fa45e52f7cdd02e00d6c9f?d=identicon&s=25 Mason Kessinger (Guest)
on 2006-01-16 20:45
What I want to do is simple.

I'd like code that prints out the name of this month (January) the next
month (February) and the one after that (March)

I've been able to print this month:

<% t = Time.now %>
<%= t.strftime(" This Month is: %B") %>

But I can't figure out how to get the next months to print out!
4913bcb685792f601ae9813b4713abb9?d=identicon&s=25 Detlef Reichl (Guest)
on 2006-01-17 01:24
(Received via mailing list)
Am Dienstag, den 17.01.2006, 04:45 +0900 schrieb Mason Kessinger:
> But I can't figure out how to get the next months to print out!
>

Try this:

irb(main):040:0* t = Time.now
=> Mon Jan 16 21:27:58 CET 2006
irb(main):041:0> m = t.mon
=> 1
irb(main):042:0> nt = Time.mktime 2006, m + 1
=> Wed Feb 01 00:00:00 CET 2006
irb(main):043:0> p nt.strftime("%B")
"February"
=> nil
irb(main):044:0> nt = Time.mktime 2006, m + 2
=> Wed Mar 01 00:00:00 CET 2006
irb(main):045:0> p nt.strftime("%B")
"March"
=> nil


Cheers
detlef
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2006-01-17 01:42
(Received via mailing list)
On Mon, 16 Jan 2006 21:42:52 +0100, Detlef Reichl
<detlef.reichl@gmx.org>
wrote:

>>
> => Wed Feb 01 00:00:00 CET 2006
> Cheers
> detlef
>
>


Time#mktime. D'oh. I feel so dense for not remembering that one.

David Vallner
9d4ec8946f933a18a1d15b094cc3c425?d=identicon&s=25 Jonathan Leighton (Guest)
on 2006-01-17 02:16
(Received via mailing list)
On Tue, 2006-01-17 at 04:45 +0900, Mason Kessinger wrote:
> But I can't figure out how to get the next months to print out!
Well you'd add the month, expressed in seconds, to the current time.
That would be:

irb(main):001:0> puts (Time.now + 60 * 60 * 24 * 30).strftime("Next
month is %B")
Next month is February
=> nil

(Assuming a month is thirty days)

You are probably using Rails (I assume), so you can do this instead:

irb(main):002:0> require_gem 'activerecord'
=> true
irb(main):003:0> puts (Time.now + 1.month).strftime("Next month is %B")
Next month is February
=> nil

Again, that assumes a month is thirty days. A more reliable way would be
to find the next month, work out its length in seconds (precisely), and
then add it to Time.now.

Jon
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2006-01-17 02:16
(Received via mailing list)
On Mon, 16 Jan 2006 20:45:18 +0100, Mason Kessinger
<masonkessinger@gmail.com> wrote:

> But I can't figure out how to get the next months to print out!
>


My first guess would be requiring "datetime", and then looking up the
month name per DateTime::MONTHNAMES[t.month + 1].

Mind you, DateTime::MONTHNAMES is one-indexed, starting from January, so
you'll have to do some index-shiftingto wrap around the end of the array
correctly. And since there's very little I hate more than shifting array
indices around, the exercise is left to the reader ;P

When I think about it, DateTime::MONTHNAMES[1..12][t.month % 12] should
work perfectly for the next month, with (t.month + 1) for the one after
that, etc.

David Vallner
05e48e632fdd0b2c25d27042f52c11d5?d=identicon&s=25 A LeDonne (Guest)
on 2006-01-17 17:07
(Received via mailing list)
On 1/16/06, Detlef Reichl <detlef.reichl@gmx.org> wrote:
> >
> => Wed Feb 01 00:00:00 CET 2006
> Cheers
> detlef
>

Along with Time.mktime, there are Date methods to shift dates by a
number of months... Date#>> and Date#<< . Which you use depends on
whether you need Dates or Times.

irb(main):022:0> require 'date'
=> true
irb(main):023:0> bob = Date.today()
=> #<Date: 4907505/2,0,2299161>
irb(main):024:0> puts bob.strftime()
2006-01-17
=> nil
irb(main):025:0> puts bob.strftime("%B")
January
=> nil
irb(main):026:0> nextmonth = bob >> 1
=> #<Date: 4907567/2,0,2299161>
irb(main):027:0> puts nextmonth.strftime()
2006-02-17
=> nil
irb(main):028:0> puts nextmonth.strftime("%B")
February
=> nil
irb(main):029:0> one_after_that = bob >> 2
=> #<Date: 4907623/2,0,2299161>
irb(main):030:0> puts one_after_that.strftime()
2006-03-17
=> nil
irb(main):031:0> puts one_after_that.strftime("%B")
March
=> nil

-A
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2006-01-21 15:40
(Received via mailing list)
On Tue, 17 Jan 2006, Detlef Reichl wrote:

> => nil
> irb(main):044:0> nt = Time.mktime 2006, m + 2
> => Wed Mar 01 00:00:00 CET 2006
> irb(main):045:0> p nt.strftime("%B")
> "March"
> => nil

but

   harp:~ > ruby -e'  p(Time::mktime(2006,13))  '
   -e:1:in `mktime': argument out of range (ArgumentError)
           from -e:1


i prefer the stupid approach:

     harp:~ > cat a.rb
     class Time
       def this_month
         strftime '%b'
       end
       def next_month n = 1
         t = dup
         s = 60 * 60 * 24
         n.times{ m = t.month; t += s until t.month != m }
         t.strftime '%b'
       end
     end

     t = Time::mktime 2006, 12
     p t.this_month
     p t.next_month
     p t.next_month(2)


     harp:~ > ruby a.rb
     "Dec"
     "Jan"
     "Feb"


regards.

-a
4913bcb685792f601ae9813b4713abb9?d=identicon&s=25 Detlef Reichl (Guest)
on 2006-01-21 15:40
(Received via mailing list)
Am Dienstag, den 17.01.2006, 07:06 +0900 schrieb ara.t.howard@noaa.gov:
> > irb(main):043:0> p nt.strftime("%B")
>    harp:~ > ruby -e'  p(Time::mktime(2006,13))  '
>    -e:1:in `mktime': argument out of range (ArgumentError)
>            from -e:1
>
>
OK

â?º: p(Time::mktime(2006,(13%12)))
Sun Jan 01 00:00:00 CET 2006


>          n.times{ m = t.month; t += s until t.month != m }
Outch :-) found no good logic? who cares, lets do it with brute force
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-01-21 15:40
(Received via mailing list)
On Jan 16, 2006, at 2:29 PM, David Vallner wrote:

> Mind you, DateTime::MONTHNAMES is one-indexed, starting from January,

We can fix that.  ;)

> so you'll have to do some index-shiftingto wrap around the end of
> the array correctly. And since there's very little I hate more than
> shifting array indices around, the exercise is left to the reader ;P

Okay, I'll bite:

 >> current = Time.now.strftime("%B")
=> "January"
 >> require "date"
=> true
 >> months = (Date::MONTHNAMES + Date::MONTHNAMES).compact
=> ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December", "January",
"February", "March", "April", "May", "June", "July", "August",
"September", "October", "November", "December"]
 >> three_months = months[months.index(current), 3]
=> ["January", "February", "March"]

James Edward Gray II
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2006-01-21 15:40
(Received via mailing list)
On Mon, 16 Jan 2006 21:55:40 +0100, James Edward Gray II
<james@grayproductions.net> wrote:

> Okay, I'll bite:
>  >> three_months = months[months.index(current), 3]
> => ["January", "February", "March"]
>
> James Edward Gray II
>
>


Ye gods, that's so idiot-proof it ain't pretty anymore amd I let my
brain
spin around index shifts.. I've been doing WAAAY too much Java at work.
Help, my 1337 Rüby h@xx0r skills are disappearing! *sic*

David Vallner
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2006-01-21 15:44
(Received via mailing list)
On Tue, 17 Jan 2006, Detlef Reichl wrote:

> OK
>
> â?º: p(Time::mktime(2006,(13%12)))
> Sun Jan 01 00:00:00 CET 2006

   harp:~ > irb
   irb(main):001:0> p(Time::mktime(2006,(48%12)))
   ArgumentError: argument out of range
           from (irb):1:in `mktime'
           from (irb):1


you need

     t = Time::now
     n = 48
     n = (t.month + n) % 12
     (n == 0 ? t : Time::mktime(1970, n)).strftime('%b')

sorry, couldn't resist!  ;-)

>>          s = 60 * 60 * 24
>>          n.times{ m = t.month; t += s until t.month != m }
>
> Outch :-) found no good logic? who cares, lets do it with brute force

hey!  i said it was stupid ;-)

cheers.

-a
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2006-01-21 15:44
(Received via mailing list)
On Tue, 17 Jan 2006, James Edward Gray II wrote:

> Okay, I'll bite:
>>> three_months = months[months.index(current), 3]
> => ["January", "February", "March"]

but

   irb(main):005:0> months[months.index(current), 42].size
   => 24

not good if the app is a mortage calculator!  ;-)

-a
4913bcb685792f601ae9813b4713abb9?d=identicon&s=25 Detlef Reichl (Guest)
on 2006-01-21 15:44
(Received via mailing list)
Am Dienstag, den 17.01.2006, 05:55 +0900 schrieb James Edward Gray II:
> Okay, I'll bite:
>  >> three_months = months[months.index(current), 3]
> => ["January", "February", "March"]
>
i don't like redundant data...


irb(main):042:0* current = Time.now.mon
=> 1
irb(main):043:0> require "date"
=> false
irb(main):044:0> months = Date::MONTHNAMES.compact
=> ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"]
irb(main):045:0> three_month = []
=> []
irb(main):046:0> (0..2).each {|i| three_month << months[(i+current-1) %
12]}
=> 0..2
irb(main):047:0> p three_month
["January", "February", "March"]
=> nil

detlef
9d0c4e1ee48f3e5a57388eafcb22abcb?d=identicon&s=25 David Brady (Guest)
on 2006-01-21 15:44
(Received via mailing list)
ara.t.howard@noaa.gov wrote:

>   irb(main):005:0> months[months.index(current), 42].size
>   => 24
>
> not good if the app is a mortage calculator!  ;-)

Sorry if this response is too late to be useful to anyone, but here's a
solution that surprised me with its elegance.  I read the OP and
immediately thought, "Oh, just spin forward 86,400 (seconds per day)
until the month changes" and, of course, someone had already posted this
reply.  However, I wrote some code as a youth that played with dates
using division and moduli, and this post got me reminiscing on that.
Here's a resurrected version.  I was very pleased to discover it handles
negative numbers, which made writing Time#prev_month trivial and
elegant.

class Time
  def next_month n=1
    t = Time::mktime year + Integer(n)/12, ((month+n-1)%12)+1
    t.strftime "%B"
  end

  def prev_month n=1
    next_month -n
  end
end

Cheers, and thanks for asking an interesting question!

-dB
This topic is locked and can not be replied to.