class Runt::WeekInterval
This class creates an expression which matches dates occuring during the weeks alternating at the given interval begining on the week containing the date used to create the instance.
WeekInterval.new(starting_date, interval)
Weeks are defined as Sunday to Saturday, as opposed to the commercial week which starts on a Monday. For example,
every_other_week = WeekInterval.new(Date.new(2013,04,24), 2)
will match any date that occurs during every other week begining with the week of 2013-04-21 (2013-04-24 is a Wednesday and 2013-04-21 is the Sunday that begins the containing week).
# Sunday of starting week every_other_week.include?(Date.new(2013,04,21)) #==> true # Saturday of starting week every_other_week.include?(Date.new(2013,04,27)) #==> true # First week _after_ start week every_other_week.include?(Date.new(2013,05,01)) #==> false # Second week _after_ start week every_other_week.include?(Date.new(2013,05,06)) #==> true
NOTE: The idea and tests for this class were originally contributed as the REWeekWithIntervalTE class by Jeff Whitmire. The behavior of the original class provided both the matching of every n weeks and the specification of specific days of that week in a single class. This class only provides the matching of every n weeks. The exact functionality of the original class is easy to create using the Runt
set operators and the DIWeek
class:
# Old way tu_thurs_every_third_week = REWeekWithIntervalTE.new(Date.new(2013,04,24),2,[2,4]) # New way tu_thurs_every_third_week = WeekInterval.new(Date.new(2013,04,24),2) & (DIWeek.new(Tuesday) | DIWeek.new(Thursday))
Notice that the compound expression (in parens after the “&”) can be replaced or combined with any other appropriate temporal expression to provide different functionality (REWeek
to provide a range of days, REDay
to provide certain times, etc…).
Contributed by Jeff Whitmire
Public Class Methods
# File lib/runt/temporalexpression.rb, line 869 def initialize(start_date,interval=2) @start_date = DPrecision.to_p(start_date,DPrecision::DAY) # convert base_date to the start of the week @base_date = @start_date - @start_date.wday @interval = interval end
Public Instance Methods
# File lib/runt/temporalexpression.rb, line 876 def include?(date) return false if @base_date > date ((adjust_for_year(date) - week_num(@base_date)) % @interval) == 0 end
# File lib/runt/temporalexpression.rb, line 881 def to_s "every #{Runt.ordinalize(@interval)} week starting with the week containing #{Runt.format_date(@start_date)}" end
Private Instance Methods
# File lib/runt/temporalexpression.rb, line 899 def adjust_for_year(date) # Exclusive range: if date.year == @base_date.year, this will be empty range_of_years = @base_date.year...date.year in_same_year = range_of_years.to_a.empty? # Week number of the given date argument week_number = week_num(date) # Default (most common case) date argument is in same year as @base_date # and the week number is also part of the same year. This starting value # is also necessary for the case where they're not in the same year. adjustment = week_number if in_same_year && (week_number < week_num(@base_date)) then # The given date occurs within the same year # but is actually week number 1 of the next year adjustment = adjustment + max_week_num(date.year) elsif !in_same_year then # Date occurs in different year range_of_years.each do |year| # Max week number taking into account we are not using commercial week adjustment = adjustment + max_week_num(year) end end adjustment end
# File lib/runt/temporalexpression.rb, line 890 def max_week_num(year) d = Date.new(year,12,31) max = week_num(d) while max < 52 d = d - 1 max = week_num(d) end max end
# File lib/runt/temporalexpression.rb, line 886 def week_num(date) # %U - Week number of the year. The week starts with Sunday. (00..53) date.strftime("%U").to_i end