How to Get Name of the Month in Ruby on Rails

how do I get name of the month in ruby on Rails?

Ref this

<% @date = Date.today  %>  
<%= @date.strftime("%B")%>

if

@date >> Fri, 11 Jun 2010

then

@date.strftime("%B") >> "June"

How can I get month name from month number

Use format string.

(Time.now + 1.month).strftime("%B")
# => "October"

Name of this month (Date.today.month as name)

Date::MONTHNAMES[Date.today.month] would give you "January". (You may need to require 'date' first).

Extract month name from string in Ruby

Date::MONTHNAMES may be able to help you. If they are always 3-character shortened versions of the months, you could build a hash to help:

dates = Date::MONTHNAMES.compact.map { |m| [m[0..2], m] }.to_h

Then use it elsewhere:

text = 'Up 4.35% from Oct to Nov'
text.gsub(/#{dates.keys.join('|')}/, dates)
=> "Up 4.35% from October to November"

Get last X month names in Rails

A slightly uglier version that builds on Olives' answer, but doesn't require looking up dates in each month and is about 31x faster:

current_month = Date.today.month

month_names = 6.downto(1).map { |n| DateTime::MONTHNAMES.drop(1)[(current_month - n) % 12] }

Output when current_month is 4 (to test Dec-Jan rollover):

["November", "December", "January", "February", "March", "April"] 

Benchmark:

Benchmark.measure do
10000.times do
current_month = Date.today.month
month_names = 6.downto(1).map { |n| DateTime::MONTHNAMES.drop(1)[(current_month - n) % 12] }
end
end
=> #<Benchmark::Tms:0x007fcfda4830d0 @label="", @real=0.12975036300485954, @cstime=0.0, @cutime=0.0, @stime=0.07000000000000006, @utime=0.06999999999999984, @total=0.1399999999999999>

Compare to the cleaner version:

Benchmark.measure do
10000.times do
5.downto(0).collect do |n|
Date::MONTHNAMES[n.months.ago.month]
end
end
end
=> #<Benchmark::Tms:0x007fcfdcbde9b8 @label="", @real=3.7730263769917656, @cstime=0.0, @cutime=0.0, @stime=0.04999999999999993, @utime=3.69, @total=3.7399999999999998>

Print month names into the view in Rails

You can get month names in

 Date::ABBR_MONTHNAMES.dup.slice(1,12)

assign them in array and loop through

EDIT
controller

months = Date::ABBR_MONTHNAMES.dup.slice(1,12)

view

<ul class="nav nav-tabs">
<% months.each do |month| %>
<li><a href="#"><%= month %></a></li>
<% end %>

</ul>

Get month names between two dates

I'd go with:

d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')

(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m, '%Y%m').mon ] }
=> ["Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"]

or:

(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ m[/\d\d$/ ].to_i ] }

which is probably a little faster.

The problem is the year boundary. You have to track years and months, not just the months, otherwise you'll remove all the duplicated month indexes when using uniq to remove the days. I went with the YYYYMM format, to get the right granularity.


require 'benchmark'
require 'date'

d1 = Date.parse('jan 1 2011')
d2 = Date.parse('dec 31 2012')

n = 100
Benchmark.bm(8) do |x|
x.report('strptime') { n.times { (d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ Date.strptime(m, '%Y%m').mon ] } } }
x.report('regex') { n.times { (d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ m[/\\d\\d$/ ].to_i ] } } }
end

user system total real
strptime 3.060000 0.020000 3.080000 ( 3.076614)
regex 2.820000 0.010000 2.830000 ( 2.829366)

EDIT:

Let's make it even more interesting.

I had some code smell that kept bugging me. I didn't like using Date.strftime and Date.strptime, so I took another run at the problem: Here are two more solutions that are running a lot faster, along with the benchmarks:

require 'benchmark'
require 'date'

def regex_months_between(d1, d2)
d1, d2 = [d1, d2].map{ |d| Date.parse(d) }.minmax

(d1..d2).map{ |m| m.strftime('%Y%m') }.uniq.map{ |m| Date::ABBR_MONTHNAMES[ m[/\d\d$/ ].to_i ] }
end

def months_between1(d1, d2)
d1, d2 = [d1, d2].map{ |d| Date.parse(d) }.minmax

months = (d2.mon - d1.mon) + (d2.year - d1.year) * 12
month_names = []
months.times{ |m|
month_names << Date::ABBR_MONTHNAMES[(d1 >> m).mon]
}
month_names << Date::ABBR_MONTHNAMES[d2.mon]
month_names
end

def months_between2(d1, d2)
d1, d2 = [d1, d2].map{ |d| Date.parse(d) }.minmax

months = (d2.mon - d1.mon) + (d2.year - d1.year) * 12
(d1.mon ... (d1.mon + months)).each_with_object(Date::ABBR_MONTHNAMES[d1.mon, 1]) { |month_offset, month_names_array|
month_names_array << Date::ABBR_MONTHNAMES[(d1 >> month_offset).mon]
}
end

puts regex_months_between('jan 1 2011', 'dec 31 2012').join(', ')
puts months_between1('jan 1 2011', 'dec 31 2012').join(', ')
puts months_between2('jan 1 2011', 'dec 31 2012').join(', ')

n = 100
Benchmark.bm(3) do |b|
b.report('rmb') { n.times { regex_months_between('jan 1 2011', 'dec 31 2012') } }
b.report('mb1') { n.times { months_between1('jan 1 2011', 'dec 31 2012') } }
b.report('mb2') { n.times { months_between2('jan 1 2011', 'dec 31 2012') } }
end

With output looking like:

Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
user system total real
rmb 2.810000 0.010000 2.820000 ( 2.820732)
mb1 0.060000 0.000000 0.060000 ( 0.057763)
mb2 0.060000 0.000000 0.060000 ( 0.057112)

Interesting. "rmb" is now running way behind. Pulling it from the tests and bumping up the loops 100x:

n = 10_000
Benchmark.bm(3) do |b|
b.report('mb1') { n.times { months_between1('jan 1 2011', 'dec 31 2012') } }
b.report('mb2') { n.times { months_between2('jan 1 2011', 'dec 31 2012') } }
end

Which gives:

        user     system      total        real
mb1 5.570000 0.060000 5.630000 ( 5.615789)
mb2 5.570000 0.040000 5.610000 ( 5.611323)

It's basically a tie between the two new ways of getting the months. Being anal, I'd go with mb2 because it'd be a little bit faster if I was doing this millions of times, but your mileage might vary.

Find month names for the last year

In Rails you can do something like this:

<% 11.downto(0) do |i| %>
<%= i.months.ago.strftime("%­B %Y") %>
<% end %>

Localize month names - Calendar Railscasts #213

You should use the localize method of I18n (shortened as l):

<h2 id="month"><%= l(@date) %></h2>

Then you can set different formats on your own:
http://guides.rubyonrails.org/i18n.html#adding-date-time-formats

# config/locales/es.yml
es:
date:
formats:
short: "%B %Y"
default: "%D %m, %Y"

And use it like this:

<h2 id="month"><%= l(@date, format: :short) %></h2>


Related Topics



Leave a reply



Submit