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

Discussion in 'Ruby' started by Mason Kessinger, Jan 16, 2006.

  1. 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!

    --
    Posted via http://www.ruby-forum.com/.
    Mason Kessinger, Jan 16, 2006
    #1
    1. Advertising

  2. On Tue, 2006-01-17 at 04:45 +0900, Mason Kessinger wrote:
    > 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!


    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

    --
    Jonathan Leighton
    http://turnipspatch.com/ | http://jonathanleighton.com/ | http://digital-proof.org/
    Jonathan Leighton, Jan 16, 2006
    #2
    1. Advertising

  3. On Mon, 16 Jan 2006 20:45:18 +0100, Mason Kessinger =20
    <> wrote:

    > 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 =3D Time.now %>
    > <%=3D t.strftime(" This Month is: %B") %>
    >
    > 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 =20
    month name per DateTime::MONTHNAMES[t.month + 1].

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

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

    David Vallner
    David Vallner, Jan 16, 2006
    #3
  4. On Mon, 16 Jan 2006 21:42:52 +0100, Detlef Reichl <>=
    =20
    wrote:

    > Am Dienstag, den 17.01.2006, 04:45 +0900 schrieb Mason Kessinger:
    >> What I want to do is simple.
    >>
    >> I'd like code that prints out the name of this month (January) the nex=

    t
    >> month (February) and the one after that (March)
    >>
    >> I've been able to print this month:
    >>
    >> <% t =3D Time.now %>
    >> <%=3D t.strftime(" This Month is: %B") %>
    >>
    >> But I can't figure out how to get the next months to print out!
    >>

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



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

    David Vallner
    David Vallner, Jan 16, 2006
    #4
  5. 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
    James Edward Gray II, Jan 16, 2006
    #5
  6. Mason Kessinger

    ako... Guest

    Re: this month, the next month, and the one after that

    a little off-topic, but a related question: does ruby have support for
    date/currency/number localisation? e.g. using comma instead of a dot in
    real numbers, month/day names in languages other than english,
    localised date format, etc?

    thanks
    konstantin
    ako..., Jan 16, 2006
    #6
  7. Am Dienstag, den 17.01.2006, 05:55 +0900 schrieb James Edward Gray II:
    > 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"]
    >

    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


    > James Edward Gray II
    >
    >
    Detlef Reichl, Jan 16, 2006
    #7
  8. On Mon, 16 Jan 2006 21:55:40 +0100, James Edward Gray II =20
    <> wrote:

    > 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 =

    =20
    >> array correctly. And since there's very little I hate more than =20
    >> shifting array indices around, the exercise is left to the reader ;P

    >
    > Okay, I'll bite:
    >
    > >> current =3D Time.now.strftime("%B")

    > =3D> "January"
    > >> require "date"

    > =3D> true
    > >> months =3D (Date::MONTHNAMES + Date::MONTHNAMES).compact

    > =3D> ["January", "February", "March", "April", "May", "June", "July", =20
    > "August", "September", "October", "November", "December", "January", =20
    > "February", "March", "April", "May", "June", "July", "August", =20
    > "September", "October", "November", "December"]
    > >> three_months =3D months[months.index(current), 3]

    > =3D> ["January", "February", "March"]
    >
    > James Edward Gray II
    >
    >



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

    David Vallner
    David Vallner, Jan 16, 2006
    #8
  9. Mason Kessinger

    Kero Guest

    On 2006-01-16, Mason Kessinger <> wrote:
    > 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!


    I can't find out how to print dates, but I do know how to get the next month
    without all the assuming-30-days mess.

    require 'date'
    Date.today.to_s
    (Date.today >> 1).to_s
    => "2006-02-16"
    (Date.today >> 2).to_s
    => "2006-03-16"
    Kero, Jan 16, 2006
    #9
  10. Mason Kessinger

    Guest

    On Tue, 17 Jan 2006, Detlef Reichl wrote:

    > 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


    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
    --
    strong and healthy, who thinks of sickness until it strikes like lightning?
    preoccupied with the world, who thinks of death, until it arrives like
    thunder? -- milarepa
    , Jan 16, 2006
    #10
  11. Mason Kessinger

    Guest

    On Tue, 17 Jan 2006, James Edward Gray II wrote:

    > 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"]


    but

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

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

    -a
    --
    strong and healthy, who thinks of sickness until it strikes like lightning?
    preoccupied with the world, who thinks of death, until it arrives like
    thunder? -- milarepa
    , Jan 16, 2006
    #11
  12. Am Dienstag, den 17.01.2006, 07:06 +0900 schrieb :
    > On Tue, 17 Jan 2006, Detlef Reichl wrote:
    >=20
    > > Try this:
    > >
    > > irb(main):040:0* t =3D Time.now
    > > =3D> Mon Jan 16 21:27:58 CET 2006
    > > irb(main):041:0> m =3D t.mon
    > > =3D> 1
    > > irb(main):042:0> nt =3D Time.mktime 2006, m + 1
    > > =3D> Wed Feb 01 00:00:00 CET 2006
    > > irb(main):043:0> p nt.strftime("%B")
    > > "February"
    > > =3D> nil
    > > irb(main):044:0> nt =3D Time.mktime 2006, m + 2
    > > =3D> Wed Mar 01 00:00:00 CET 2006
    > > irb(main):045:0> p nt.strftime("%B")
    > > "March"
    > > =3D> nil

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

    OK

    =E2=98=BA: p(Time::mktime(2006,(13%12)))
    Sun Jan 01 00:00:00 CET 2006


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


    Outch :) found no good logic? who cares, lets do it with brute force

    > t.strftime '%b'
    > end
    > end
    >=20
    > t =3D Time::mktime 2006, 12
    > p t.this_month
    > p t.next_month
    > p t.next_month(2)
    >=20
    >=20
    > harp:~ > ruby a.rb
    > "Dec"
    > "Jan"
    > "Feb"
    >=20
    >=20
    > regards.
    >=20
    > -a
    Detlef Reichl, Jan 16, 2006
    #12
  13. Mason Kessinger

    Guest

    On Tue, 17 Jan 2006, Detlef Reichl wrote:

    > OK
    >
    > =E2=98=BA: 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 =3D Time::now
    n =3D 48
    n =3D (t.month + n) % 12
    (n =3D=3D 0 ? t : Time::mktime(1970, n)).strftime('%b')

    sorry, couldn't resist! ;-)

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

    >
    > Outch :) found no good logic? who cares, lets do it with brute force


    hey! i said it was stupid ;-)

    cheers.

    -a
    --=20
    strong and healthy, who thinks of sickness until it strikes like lightning?
    preoccupied with the world, who thinks of death, until it arrives like
    thunder? -- milarepa
    , Jan 16, 2006
    #13
  14. Mason Kessinger

    A LeDonne Guest

    On 1/16/06, Detlef Reichl <> wrote:
    > Am Dienstag, den 17.01.2006, 04:45 +0900 schrieb Mason Kessinger:
    > > 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 =3D Time.now %>
    > > <%=3D t.strftime(" This Month is: %B") %>
    > >
    > > But I can't figure out how to get the next months to print out!
    > >

    >
    > Try this:
    >
    > irb(main):040:0* t =3D Time.now
    > =3D> Mon Jan 16 21:27:58 CET 2006
    > irb(main):041:0> m =3D t.mon
    > =3D> 1
    > irb(main):042:0> nt =3D Time.mktime 2006, m + 1
    > =3D> Wed Feb 01 00:00:00 CET 2006
    > irb(main):043:0> p nt.strftime("%B")
    > "February"
    > =3D> nil
    > irb(main):044:0> nt =3D Time.mktime 2006, m + 2
    > =3D> Wed Mar 01 00:00:00 CET 2006
    > irb(main):045:0> p nt.strftime("%B")
    > "March"
    > =3D> nil
    >
    >
    > 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'
    =3D> true
    irb(main):023:0> bob =3D Date.today()
    =3D> #<Date: 4907505/2,0,2299161>
    irb(main):024:0> puts bob.strftime()
    2006-01-17
    =3D> nil
    irb(main):025:0> puts bob.strftime("%B")
    January
    =3D> nil
    irb(main):026:0> nextmonth =3D bob >> 1
    =3D> #<Date: 4907567/2,0,2299161>
    irb(main):027:0> puts nextmonth.strftime()
    2006-02-17
    =3D> nil
    irb(main):028:0> puts nextmonth.strftime("%B")
    February
    =3D> nil
    irb(main):029:0> one_after_that =3D bob >> 2
    =3D> #<Date: 4907623/2,0,2299161>
    irb(main):030:0> puts one_after_that.strftime()
    2006-03-17
    =3D> nil
    irb(main):031:0> puts one_after_that.strftime("%B")
    March
    =3D> nil

    -A
    A LeDonne, Jan 17, 2006
    #14
  15. Francis Hwang, Jan 17, 2006
    #15
  16. Re: this month, the next month, and the one after that

    Just to compliment what was said above, you can do the following things
    on a Date:
    d = Date.today
    d + 1 => Next Day
    d - 1 => Previous Day
    d >> 1 => Next Month
    d << 1 => Previous Month

    This is preferable to adding a known number of seconds to a time as is
    done with Rails (time + 2.months) or in the posts above since months
    can have a variable number of days, and your calculations will start to
    get odd.

    .adam
    Adam Sanderson, Jan 17, 2006
    #16
  17. Mason Kessinger

    David Brady Guest

    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

    --
    David Brady

    C++ Guru. Ruby nuby. Apply salt as needed.
    David Brady, Jan 20, 2006
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michal Maciejczak
    Replies:
    1
    Views:
    1,971
    Matthias Kaeppler
    Apr 23, 2005
  2. Bill
    Replies:
    10
    Views:
    721
    Fulvio
    Apr 13, 2006
  3. Replies:
    1
    Views:
    435
    Steve W. Jackson
    Dec 22, 2006
  4. Deniz Bahar
    Replies:
    2
    Views:
    453
    Andrey Tarasevich
    Mar 9, 2005
  5. Mufasa
    Replies:
    0
    Views:
    388
    Mufasa
    Sep 5, 2008
Loading...

Share This Page