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


#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!


#2

Am Dienstag, den 17.01.2006, 04:45 +0900 schrieb Mason K.:

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


#3

On Mon, 16 Jan 2006 21:42:52 +0100, Detlef R.
removed_email_address@domain.invalid
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 V.


#4

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


#5

On Mon, 16 Jan 2006 20:45:18 +0100, Mason K.
removed_email_address@domain.invalid 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 :stuck_out_tongue_winking_eye:

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 V.


#6

On 1/16/06, Detlef R. removed_email_address@domain.invalid 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


#7

On Tue, 17 Jan 2006, Detlef R. 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


#8

On Jan 16, 2006, at 2:29 PM, David V. wrote:

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

We can fix that. :wink:

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 :stuck_out_tongue_winking_eye:

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 G. II


#9

Am Dienstag, den 17.01.2006, 07:06 +0900 schrieb removed_email_address@domain.invalid:

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 :slight_smile: found no good logic? who cares, lets do it with brute force


#10

On Mon, 16 Jan 2006 21:55:40 +0100, James Edward G. II
removed_email_address@domain.invalid wrote:

Okay, I’ll bite:

three_months = months[months.index(current), 3]
=> [“January”, “February”, “March”]

James Edward G. 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 V.


#11

On Tue, 17 Jan 2006, Detlef R. 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! :wink:

     s = 60 * 60 * 24
     n.times{ m = t.month; t += s until t.month != m }

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

hey! i said it was stupid :wink:

cheers.

-a


#12

Am Dienstag, den 17.01.2006, 05:55 +0900 schrieb James Edward G. 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


#13

On Tue, 17 Jan 2006, James Edward G. 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! :wink:

-a


#14

removed_email_address@domain.invalid wrote:

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

not good if the app is a mortage calculator! :wink:

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