Skip to content

Commit

Permalink
Merge 9a5dafc into 888ea54
Browse files Browse the repository at this point in the history
  • Loading branch information
chylauSF committed Aug 29, 2017
2 parents 888ea54 + 9a5dafc commit 5b327bd
Show file tree
Hide file tree
Showing 7 changed files with 860 additions and 184 deletions.
4 changes: 2 additions & 2 deletions Gemfile.lock
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
merch_calendar (0.1.0)
merch_calendar (0.2.0)

GEM
remote: https://www.rubygems.org/
Expand Down Expand Up @@ -58,4 +58,4 @@ DEPENDENCIES
simplecov

BUNDLED WITH
1.15.1
1.15.3
166 changes: 75 additions & 91 deletions lib/merch_calendar/merch_week.rb
@@ -1,6 +1,6 @@
module MerchCalendar

# Represents the Merch Week for a specified date.
# Represents the Merch Week for a specified date and calendar
class MerchWeek

MONTHS = %w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec).freeze
Expand All @@ -10,56 +10,68 @@ class MerchWeek
# @!attribute [r] date
# @return [Date] the date for this merch week
attr_reader :date

class << self

# Locates the +MerchWeek+ for a given Julian date.
#
# @overload from_date(String)
# @param [String] julian_date a julian date in the format of +YYYY-MM-DD+
# @overload from_date(Date)
# @param [Date] julian_date a +Date+ object
#
# @return [MerchWeek]
def from_date(julian_date)
MerchWeek.new Date.parse("#{julian_date}")
end

# Returns an array of merch weeks for a month, or a specific week.
#
# @overload find(year, julian_month)
# Returns an array of +MerchWeek+s for a given month
# @param year [Fixnum] the merch year to locate
# @param julian_month [Fixnum] the month to find merch months for
# @return [Array<MerchWeek>]
# @overload find(year, julian_month, week_number)
# @param year [Fixnum] the merch year to locate
# @param julian_month [Fixnum] the month to find merch months for
# @param week_number [Fixnum] the specific week number.
# @return [MerchWeek] the specific merch week
def find(year, julian_month, week_number=nil)
if week_number.nil?
MerchCalendar.weeks_for_month(year, julian_month)
else
MerchCalendar.weeks_for_month(year, julian_month)[week_number-1]
end
end

# Returns the +MerchWeek+ for today's date
#
# @return [MerchWeek]
def today
MerchWeek.from_date Date.today

# The Merch Calendar that is being represented, either Fiscal or Retail
#
# @!attribute [r] calendar
# @return [Class] the calendar that determines the merch week
attr_reader :calendar

# Locates the +MerchWeek+ for a given Julian date.
#
# @overload from_date(String)
# @param [String] julian_date a julian date in the format of +YYYY-MM-DD+
# @param [Hash] opts the options to set your calendar, if none it will default to RetailCalendar
# # @option opts [Class] :calendar The Calendar Class
# @overload from_date(Date)
# @param [Date] julian_date a +Date+ object
# @param [Hash] opts the options to set your calendar, if none it will default to RetailCalendar
# # @option opts [Class] :calendar The Calendar Class
# @return [MerchWeek]
def self.from_date(julian_date, options = {})
MerchWeek.new(Date.parse("#{julian_date}"), options)
end

# Returns an array of merch weeks for a month, or a specific week.
#
# @overload find(year, julian_month, week_number=nil, options)
# Returns an array of +MerchWeek+s for a given month
# @param year [Fixnum] the merch year to locate
# @param julian_month [Fixnum] the month to find merch months for
# @param week_number [Nil] set week_number to nil
# @param options [Hash] options to set your calendar, if none it will default to RetailCalendar
# @return [Array<MerchWeek>]
# @overload find(year, julian_month, week_number)
# @param year [Fixnum] the merch year to locate
# @param julian_month [Fixnum] the month to find merch months for
# @param week_number [Fixnum] the specific week number.
# @param options [Hash] options to set your calendar, if none it will default to RetailCalendar
# @return [MerchWeek] the specific merch week
def self.find(year, julian_month, week_number=nil, options={})
calendar = options.fetch(:calendar, RetailCalendar.new)
if week_number.nil?
calendar.weeks_for_month(year, julian_month)
else
calendar.weeks_for_month(year, julian_month)[week_number-1]
end
end


# Returns the +MerchWeek+ for today's date
#
# @param [Hash] opts the options to set your calendar, if none it will default to RetailCalendar
# # @option opts [Class] :calendar The Calendar Class
# @return [MerchWeek]
def self.today(options={})
MerchWeek.from_date(Date.today, options)
end

# Pass in a date, make sure it is a valid date object
# @private
def initialize(date, options = {})
@date = date


#defaults to Retail Calendar if no other calendar is defined
@calendar = options.fetch(:calendar, RetailCalendar.new)
# Placeholders. These should be populated by functions if nil
# week_start: nil, week_end: nil, week_number: nil
@start_of_year = options[:start_of_year]
Expand All @@ -81,108 +93,96 @@ def year_week
end

# This returns the "merch month" number for a date
# Merch months are shifted by one. Month 1 is Feb
# Month 1 is Feb for the retail calendar
# Month 1 is August for the fiscal calendar
#
# @return [Fixnum]
def merch_month
# TODO: This is very inefficient, but less complex than strategic guessing
# maybe switch to a binary search or something
merch_year = calendar.merch_year_from_date(date)
@merch_month ||= (1..12).detect do |num|
retail_calendar.end_of_month(start_of_year.year, num) >= date && date >= retail_calendar.start_of_month(start_of_year.year, num)
calendar.end_of_month(merch_year, num) >= date && date >= calendar.start_of_month(merch_year, num)
end
end

# The merch year
# Returns the Merch year depending whether it is from the Retail or Fiscal calendar
#
# @return [Fixnum]
def year
start_of_year.year
@year ||= calendar.merch_year_from_date(date)
end

# The julian month that this merch week falls in
# Returns julian month where the merch week falls
#
# @return [Fixnum]
def month
@month ||= MerchCalendar.merch_to_julian(merch_month)
@month ||= calendar.merch_to_julian(merch_month)
end

# The specific quarter this week falls in
# Returns the quarter that this merch week falls
#
# @return [Fixnum]
def quarter
case merch_month
when 7,8,9
return 1
when 10,11,12
return 2
when 1,2,3
return 3
else
return 4
end
@quarter ||= calendar.quarter(merch_month)
end

# Returns the date of the start of this week
# Returns the start date of this week
#
# @return [Date]
def start_of_week
@start_of_week ||= (start_of_month + (7 * (week - 1)))
end

# Returns the date of the end of this week
# Returns the end date of this week
#
# @return [Date]
def end_of_week
@end_of_week ||= (start_of_week + 6)
end

# the number of the week within the given month
# The number of the week within the given merch month
# will be between 1 and 5
#
# @return [Fixnum]
def week
@week ||= (((date-start_of_month)+1)/7.0).ceil
end

# The date of the start of the corresponding merch year
# The start date of the corresponding merch year
#
# @return [Date]
def start_of_year
@start_of_year ||= year_start_date
@start_of_year ||= calendar.start_of_year(year)
end

# The end date of the corresponding merch year
#
# @return [Date]
def end_of_year
@end_of_year ||= retail_calendar.end_of_year(year)
@end_of_year ||= calendar.end_of_year(year)
end

# The start date of the merch month
#
# @return [Date]
def start_of_month
@start_of_month ||= retail_calendar.start_of_month(year, merch_month)
@start_of_month ||= calendar.start_of_month(year, merch_month)
end

# The end date of the merch month
#
# @return [Date]
def end_of_month
@end_of_month ||= retail_calendar.end_of_month(year, merch_month)
@end_of_month ||= calendar.end_of_month(year, merch_month)
end

# The merch season this date falls under.
# Returns a string of +Fall/Winter+ or +Spring/Summer+
#
# THIS MIGHT NEED TO CHANGE DEPENDING ON THE CALENDAR
# @return [String]
def season
case merch_month
when 1,2,3,4,5,6
"Spring/Summer"
when 7,8,9,10,11,12
"Fall/Winter"
end
@season ||= calendar.season(merch_month)
end

# Outputs a text representation of this merch week
Expand All @@ -193,7 +193,6 @@ def season
# * +:elasticsearch+ (default) "2012-12w05"
#
# @param format [Symbol] the format identifier to return. Default is +:short+
#
# @return [Date]
def to_s(format = :short)
case format
Expand All @@ -205,20 +204,5 @@ def to_s(format = :short)
"#{MONTHS[month - 1]} W#{week}"
end
end

private

def year_start_date
start_date = retail_calendar.start_of_year(date.year)
if start_date > date
start_date = retail_calendar.start_of_year(date.year - 1)
end
start_date
end

def retail_calendar
@retail_calendar ||= RetailCalendar.new
end

end
end

0 comments on commit 5b327bd

Please sign in to comment.