dwkns
dwkns

Reputation: 2449

How do I get the first Thursday of the month in Ruby/Rails?

The following Ruby code gets me the first day of each month :

require 'active_support/all'

# get the date at the beginning of this month
date = Date.today.beginning_of_month

# get the first day of the next 5 months
5.times do |num|
  date = date.next_month
  p date
end

Which gives :

=> Fri, 01 Aug 2014
=> Mon, 01 Sep 2014
=> Wed, 01 Oct 2014
=> Sat, 01 Nov 2014
=> Mon, 01 Dec 2014

But how do I get the first Thursday of each month? i.e.

=> Thu, 07 Aug 2014
=> Thu, 04 Sep 2014
=> Thu, 02 Oct 2014
=> Thu, 06 Nov 2014
=> Thu, 04 Dec 2014

Upvotes: 4

Views: 1651

Answers (6)

Eric Hubbell
Eric Hubbell

Reputation: 49

I ran into this problem for a recurring_events feature that I needed to build. I changed some of the variables to find the first Thursday but it also shows how you could evolve the answer to find the 2nd or 3rd Thursday (or any day of the week for that matter) if you had a week and day of the week count.

def find_thursday
  start_of_month = DateTime.now.beginning_of_month
  month_day = nil
  loop do
    month_day = start_of_month += 1.day
    break if month_day.wday == find_weekday("Thu")
  end
  return month_day
end


def find_weekday
  d = default_weekdays.find { |d| d[:day] == start_date.strftime("%a") }
  d[:count]
end


def default_weekdays
  return [
    { day: 'Sun', count: 0 },
    { day: 'Mon', count: 1 },
    { day: 'Tue', count: 2 },
    { day: 'Wed', count: 3 },
    { day: 'Thu', count: 4 },
    { day: 'Fri', count: 5 },
    { day: 'Sat', count: 6 },
  ]
end

Upvotes: -1

Roman Kiselenko
Roman Kiselenko

Reputation: 44360

That my opinion:

date_begin = Date.today.beginning_of_month
date_end = date_begin + 5.month
[*date_begin..date_end].select(&:thursday?).uniq(&:month)
=> [Thu, 03 Jul 2014, Thu, 07 Aug 2014, Thu, 04 Sep 2014, Thu, 02 Oct 2014, Thu, 06 Nov 2014]

Upvotes: 4

xlembouras
xlembouras

Reputation: 8295

you can use something like this:

def first_thursday(months_ahead)
  start_of_month = months_ahead.months.from_now.beginning_of_month.to_date
  start_of_month += (4 - start_of_month.cwday) % 7
end

first_thursday 1
=> Thu, 07 Aug 2014
first_thursday 2
=> Thu, 04 Sep 2014

Upvotes: 1

AndreDurao
AndreDurao

Reputation: 5795

There's no need for iterations or conditions just get the so called delta of days till next thursday:

#4 is thursday because wday starts at 0 (sunday)

date = Date.today.beginning_of_month
date += (4 - date.wday) % 7
p date
=> Thu, 03 Jul 2014

Upvotes: 10

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230326

Just for fun

class Date
  def skip_to_thursday
    # given current weekday, how many days we need to add for it to become thursday
    # for example, for monday (weekday 1) it's 3 days

    offset = lambda {|x| (4-x) % 7 }    
    self + offset[wday]
  end
end


# get the date at the beginning of this month
date = Date.today.beginning_of_month

date.skip_to_thursday # => Thu, 03 Jul 2014

Upvotes: 4

Arup Rakshit
Arup Rakshit

Reputation: 118271

Here is my way :

def first_thursday
  date = Date.today.beginning_of_month
  date += 1 until date.wday == 4
  date
end

first_thursday # => Thu, 03 Jul 2014 

Upvotes: 2

Related Questions