如何确定某个月的第n个工作日?

时间:2013-11-29 10:33:37

标签: ruby-on-rails ruby

这段代码决定了某个月第n个工作日的日期。

示例:2013年12月的第2个星期二:

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

2013年12月的最后一个星期日:

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

我无法找到这个问题的工作代码,所以我分享了自己的代码。

3 个答案:

答案 0 :(得分: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 :(得分: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)

答案 2 :(得分: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