user1725651
user1725651

Reputation: 159

How to calculate the current week in the month in Ruby

My goal is to find the date of a particular day in a given week of that month. Say for example, I want to know the date on May 2nd week's Friday. I can get the following via Time and Date classes.

Week number of current year (considering Sunday as first)

    Time.strftime(%U)

Day of the week (0..7)

    Time.strftime(%w)

But how I get the what week (1st,2nd,3rd,4th or 5th) of the month it is in?

Thanks in advance!

Upvotes: 3

Views: 4728

Answers (6)

drewish
drewish

Reputation: 9369

I think the dependency free version would be:

def week_of_month date
  first_of_month = Date.new(date.year, date.month, 1)
  partial_first_week = date.cwday >= first_of_month.cwday ? 1 : 0
  (date.cweek - first_of_month.cweek) + partial_first_week
end

Upvotes: -1

There is a cool way to calc it in Rails:

dt.cweek - dt.beginning_of_month.cweek + 1

Upvotes: -1

Ruby developer
Ruby developer

Reputation: 1

def number_of_weeks_month(start_of_month, count, end_of_month)
    if start_date > end_of_month
        return count
    else
        number_of_weeks_month(start_date.end_of_week + 1, count + 1, end_of_month)
    end
end

number_of_weeks_month(Date.parse("2017-11-01"),0,Date.parse("2017-11-30")) for the month on November it gives 4

Upvotes: 0

rsnorman15
rsnorman15

Reputation: 510

In order to handle the requirements you listed, I would suggest writing a helper function to get the number of the week in a month.

def get_month_week(date_or_time, start_day = :sunday)

  date = date_or_time.to_date
  week_start_format = start_day == :sunday ? '%U' : '%W'

  month_week_start = Date.new(date.year, date.month, 1)
  month_week_start_num = month_week_start.strftime(week_start_format).to_i
  month_week_start_num += 1 if month_week_start.wday > 4 # Skip first week if doesn't contain a Thursday

  month_week_index = date.strftime(week_start_format).to_i - month_week_start_num
  month_week_index + 1 # Add 1 so that first week is 1 and not 0

end

This can then just be called like so:

get_month_week(Date.today)

If you really feel like monkey-patching is something you want, you can add to the Date class:

class Date

  def month_week(start_day = :sunday)

    week_start_format = start_day == :sunday ? '%U' : '%W'

    month_week_start = Date.new(self.year, self.month, 1)
    month_week_start_num = month_week_start.strftime(week_start_format).to_i
    month_week_start_num += 1 if month_week_start.wday > 4 # Skip first week if doesn't contain a Thursday

    month_week_index = self.strftime(week_start_format).to_i - month_week_start_num
    month_week_index + 1 # Add 1 so that first week is 1 and not 0

  end

end

And this can be called on a date or time like so:

Date.today.month_week

or

Time.current.to_date.month_week

I would advise against this since it may collide with other libraries or violate least-surprise for other developers working on the project.

Upvotes: 3

vladra
vladra

Reputation: 186

You can try this:

current_time = Time.zone.now
beginning_of_the_month = current_time.beginning_of_month
puts current_time.strftime('%U').to_i - beginning_of_the_month.strftime('%U').to_i + 1

Or

Time.parse('2015-01-08').strftime('%U').to_i - Time.parse('2015-01-01').strftime('%U').to_i + 1

Upvotes: 3

infused
infused

Reputation: 24337

The week-of-month gem will do this. First add the gem to your Gemfile:

gem 'week_of_month'

Then use it like:

Time.now.week_of_month

If you need the week to start on Monday instead of Sunday. Stick this in an initializer:

WeekOfMonth.configuration.monday_active = true

Upvotes: 1

Related Questions