Как мне получить первый четверг месяца в Ruby / Rails?

#ruby-on-rails #ruby

#ruby-on-rails #ruby

Вопрос:

Следующий код Ruby возвращает мне первый день каждого месяца :

 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
  

Что дает :

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

Но как мне получить первый четверг каждого месяца? т.е.

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

Ответ №1:

Нет необходимости в итерациях или условиях, просто получите так называемую дельту дней до следующего четверга:

 #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
  

Ответ №2:

Это мое мнение:

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

Комментарии:

1. в haskell это, вероятно, было бы очень эффективно. В ruby — не так много 🙂

2. .map { |x| x if x.thursday? }.compact => .select(amp;:thursday?)

Ответ №3:

Просто для удовольствия

 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
  

Комментарии:

1. Я такой тупой.. кто все еще не понимает.. что этот хэш там делает .. можете ли вы сказать несколько слов для меня ? 🙂

2. попробуйте забавную лямбду: offset = lambda {|x| (4-x) % 7 } , чтобы вы могли использовать offset[2] #=> 2

3. @xlembouras: ого, умница 🙂

4. Или offset = [4,3,2,1,7,6] и offset.index(wday)

5. Правильно-правильно. Это то, что было в первой версии. Посмотрите на историю редактирования 🙂

Ответ №4:

Вот мой способ :

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

first_thursday # => Thu, 03 Jul 2014 
  

Ответ №5:

вы можете использовать что-то вроде этого:

 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
  

Комментарии:

1. Не работает для июля или сентября. На самом деле, это, вероятно, чистая удача, что это работает в августе 🙂

Ответ №6:

Я столкнулся с этой проблемой для recurring_events функции, которую мне нужно было создать. Я изменил некоторые переменные, чтобы найти первый четверг, но это также показывает, как вы могли бы развить ответ, чтобы найти 2-й или 3-й четверг (или любой день недели, если на то пошло), если у вас была неделя и количество дней недели.

 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