I'm sure there's a good simple elegant one-liner in Ruby to give you the number of days in a given month, accounting for year, such as "February 1997". What is it?
13 Answers
If you're working in Rails, chances are you'll get hamstrung eventually if you switch among Time
, Date
, and DateTime
, especially when it comes to dealing with UTC/time zones, daylight savings, and the like. My experience has been it's best to use Time
, and stick with it everywhere.
So, assuming you're using Rails's Time class, there are two good options, depending on context:
If you have a month
m
and yeary
, use the class method onTime
:days = Time.days_in_month(m, y)
If you have a Time object
t
, cleaner to ask the day number of the last day of the month:days = t.end_of_month.day

- 95,083
- 20
- 220
- 214

- 1,487
- 2
- 9
- 5
-
8Thanks! but not really -- OP asked about ruby, not rails. I'd be interested to know how many folks are working in Ruby Off Rails, though. – mkosma Oct 17 '12 at 22:19
-
14I use ruby outside rails and this answer would be no good for me. – SteveRawlinson Sep 06 '13 at 14:37
-
1@SteveRawlingson Get your career on track then! :P – Starkers Feb 22 '14 at 20:44
-
2I'm implementing a gem where this is needed, and I cannot assume the user would use the gem inside Rails. So I really think that, although cleaner, this should not be the accepted answer. It's very nice to have it here in context as well, cause lots of people would prefer this option when in Rails. – Ernesto Oct 02 '14 at 15:04
-
Working on Ruby project do not forbid you using activesupport gem. Source : https://github.com/rails/rails/tree/master/activesupport – OmniBus Feb 05 '15 at 06:56
-
I don't use Rails, but generally I find the time stuff from ActiveSupport is worth cherry-picking into any project that deals with dates and times like this. – Andrew Feb 09 '17 at 22:21
require 'date'
def days_in_month(year, month)
Date.new(year, month, -1).day
end
# print number of days in February 2012
puts days_in_month(2012, 2)
-
-
4You only didn't need to require date because it has already been required elsewhere. – Kris May 18 '18 at 08:46
This is the implementation from ActiveSupport (a little adapted):
COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
def days_in_month(month, year = Time.now.year)
return 29 if month == 2 && Date.gregorian_leap?(year)
COMMON_YEAR_DAYS_IN_MONTH[month]
end

- 2,685
- 19
- 23
How about:
require 'date'
def days_in_month(year, month)
(Date.new(year, 12, 31) << (12-month)).day
end
# print number of days in Feburary 2009
puts days_in_month(2009, 2)
You may also want to look at Time::days_in_month in Ruby on Rails.
-
1Could you explain what make this def? Because I like but I want to understand – Bruce_Warrior Oct 15 '12 at 01:25
-
1@Mike Wade, this assumes we know December has 31 days. What about if we don't even know that? – JWL Nov 02 '12 at 07:08
-
5
-
1@nemesisfixx, you can work off Jan 1 instead of Dec 31. ((Date.new(year+1, 1, 1) - 1.day) << (12-month)).day – Isaac Betesh Apr 05 '13 at 18:55
-
@IsaacBetesh, yep get it `((Date.new(2013+1, 1, 1) - day_offset) << (12-month)).day` works for me :-) – JWL Apr 08 '13 at 06:24
-
3`<< (12-month)).day` doesn't seem very readable / understandable / maintainable, whereas `year, month, -1` seems much more obvious - to me. – Michael Durrant Oct 18 '13 at 13:25
In Rails project for current date
Time.days_in_month(Time.now.month, Time.now.year)
For any date t which is instance of Time
Time.days_in_month(t.month, t.year)
or
t.end_of_month.day
.
If you have UTC seconds, you need to get an instance of Time first
Time.at(seconds).end_of_month.day

- 16,236
- 7
- 69
- 80
For a given Date object I feel like the easiest is:
Date.today.all_month.count

- 1,368
- 14
- 18
-
1Docs for `all_month` can be found [here](https://api.rubyonrails.org/classes/DateAndTime/Calculations.html#method-i-all_month). – Marian13 Oct 19 '20 at 01:28
Use Time.days_in_month(month)
where month = 1
for January, 2
for Feb, etc.

- 95,083
- 20
- 220
- 214

- 21,258
- 32
- 119
- 207
revise the input for other format
def days_in_a_month(date = "2012-02-01")
date.to_date.end_of_month.day
end

- 36,908
- 70
- 97
- 130

- 125
- 3
- 8
as of rails 3.2... there's a built in version: http://api.rubyonrails.org/classes/Time.html#method-c-days_in_month
(alas, it shows up after this answer, which takes folks on a long hike)

- 208
- 1
- 12
Time.now.end_of_month.day
- for current month
Date.parse("2014-07-01").end_of_month.day
- use date of first day in month.
Depends on ActiveSupport

- 201
- 1
- 4
A simple way using Date
:
def days_of_month(month, year)
Date.new(year, month, -1).day
end

- 503
- 4
- 7
I think it's the simplest way to get it
def get_number_of_days(date = Date.today)
Date.new(date.year, date.month, -1).mday
end

- 331
- 1
- 5
Since the time is irrelevant for this purpose then you just need a date object:
[*Date.today.all_month].size

- 131
- 1
- 8
-
Time is not irrelevant, the OP wants to know the number of days *in a given month, such as february 1997* – Nino Filiu Jan 02 '19 at 17:35
-
What I meant is that since we don't need either hours, minutes or seconds then a Time object is not necessary. Therefore, a Date object is more than enough in this case. – Andres Leon Jan 03 '19 at 10:33
-
I prefer to use a Time object when I can, so as not to have to pull the Date object from the library. – BobRodes Mar 07 '19 at 20:47