简体   繁体   中英

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? ie

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

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

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

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]

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 

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM