module Octopolo class Week attr_accessor :year attr_accessor :number DATE_STRING_FORMAT = "%Y-%m-%d" # Public: Instantiate a new Week # # year - Year the week occurs in # number - The number of the week in the given year def initialize year, number self.year = year self.number = number end # Public: Parse the date from a date-ish object # # dateish - A Date, Time, or String representing a date or time def self.parse dateish # TODO i'm not 100% happy with this implementation, but it does what i want and the tests pass if dateish.respond_to? :to_date date = dateish.to_date new date.year, date.cweek else date = Date.parse(dateish.to_s) new date.year, date.cweek end rescue ArgumentError raise InvalidType end # Public: Instantiate a Week for the current week # # Returns an instance of Week def self.current today = Date.today Week.new today.cwyear, today.cweek end # Public: Instantiate a Week for the prior week # # Returns an instance of Week def self.prior current.previous end # Public: A list of the last N weeks, excluding the current week # # count - An integer listing the number of weeks to return # # Returns an Array of Week instances def self.last count # holy hell this is gnarly # # essentially, create an array with the current week in it, then loop # through and tack on the previous week for whichever week is last; this # way, we keep tacking on ever more previous weeks as many times as is # asked for. out = [prior] (count - 1).times do out << out.last.previous end out end # Public: Friendly string representation of the week # # Returns a String of the start date def to_s start_date.strftime(DATE_STRING_FORMAT) end # Public: Programmer-friendly representation of the week # # Returns a String containing object details def inspect "#<#{self.class} #{to_s} (year=#{year} number=#{number})>" end # Public: Whether the week is the same as another week # # Returns a Boolean def == other year == other.year && number == other.number rescue false end # Public: The previous week # # Returns an instance of Week def previous if number == 1 # carry the 1 Week.new year - 1, 52 else Week.new year, number - 1 end end # Public: The next week # # Returns an instance of Week def next if number == 52 # carry the 1 Week.new year + 1, 1 else Week.new year, number + 1 end end # Public: Monday that starts the week # # Returns an instance of Date def start_date Date.commercial year, number end # Public: Sunday that ends the week # # Returns an instance of Date def end_date Date.commercial year, number, 7 end InvalidType = Class.new(StandardError) end end