2013-11-29 3 views
2

Этот фрагмент кода определяет дату для n-го дня недели данного месяца.Как определить n-й день недели за данный месяц?

Пример: для 2-ой вторник декабря 2013 года:

>> nth_weekday(2013,11,2,2) 
=> Tue Nov 12 00:00:00 UTC 2013 

Последнее воскресенье декабря 2013 года:

>> nth_weekday(2013,12,'last',0) 
=> Sun Dec 29 00:00:00 UTC 2013 

Я не смог найти рабочий код на этот вопрос, так что я делю мой собственный.

ответ

0
# nth can be 1..4 or 'last' 
def nth_weekday(year,month,nth,week_day) 
    first_date = Time.gm(year,month,1) 
    last_date = month < 12 ? Time.gm(year,month+1)-1.day : Time.gm(year+1,1)-1.day 

    date = nil 
    if nth.class == Fixnum and nth > 0 and nth < 5 
     date = first_date 
     nth_counter = 0 
     while date <= last_date 
      nth_counter += 1 if date.wday == week_day 
      nth_counter == nth ? break : date += 1.day 
     end 
    elsif nth == 'last' 
     date = last_date 
     while date >= first_date 
      date.wday == week_day ? break : date -= 1.day 
     end 
    else 
     raise 'Error: nth_weekday called with out of range parameters' 
    end 
    return date 
end 
4

Если вы используете Rails, вы можете сделать это.

def nth_weekday(year, month, n, wday) 
    first_day = DateTime.new(year, month, 1) 
    arr = (first_day..(first_day.end_of_month)).to_a.select {|d| d.wday == wday } 
    n == 'last' ? arr.last : arr[n - 1] 
end 

> n = nth_weekday(2013,11,2,2) 
# => Tue, 12 Nov 2013 00:00:00 +0000 
1

Вы можете использовать:

require 'date' 

class Date 

    #~ class DateError < ArgumentError; end 

    #Get the third monday in march 2008: new_by_mday(2008, 3, 1, 3) 
    # 
    #Based on http://forum.ruby-portal.de/viewtopic.php?f=1&t=6157 
    def self.new_by_mday(year, month, weekday, nr) 

    raise(ArgumentError, "No number for weekday/nr") unless weekday.respond_to?(:between?) and nr.respond_to?(:between?) 
    raise(ArgumentError, "Number not in Range 1..5: #{nr}") unless nr.between?(1,5) 
    raise(ArgumentError, "Weekday not between 0 (Sunday)and 6 (Saturday): #{nr}") unless weekday.between?(0,6) 

    day = (weekday-Date.new(year, month, 1).wday)%7 + (nr-1)*7 + 1 

    if nr == 5 
     lastday = (Date.new(year, (month)%12+1, 1)-1).day # each december has the same no. of days 
     raise "There are not 5 weekdays with number #{weekday} in month #{month}" if day > lastday 
    end 

    Date.new(year, month, day) 
    end 
end 
p Date.new_by_mday(2013,11,2,2) 

Это также available in a gem:

gem "date_tools", "~> 0.1.0" 
require 'date_tools/date_creator' 
p Date.new_by_mday(2013,11,2,2) 
Смежные вопросы