Reputation: 2777
I created this basic class right here:
class TimePeriod
MONTHS_PER_QUARTER = 3
QUARTER_RANGE = {
0 => [1,3],
1 => [4,6],
2 => [7,9],
3 => [10,12]
}
def self.quarter(month_num)
(month_num - 1) / MONTHS_PER_QUARTER
end
def self.quarter_range(month_num)
quarter = quarter month_num
t1,t2 = QUARTER_RANGE[quarter]
[Time.parse(Date::MONTHNAMES[t1]).beginning_of_month, Time.parse(Date::MONTHNAMES[t2]).end_of_month]
end
end
It gives me a time range for a quarter, given a month provided as an integer:
> TimeUtils.quarter_range(Time.now.month)
=> [2015-04-01 00:00:00 -0400, 2015-06-30 23:59:59 -0400]
So it works. However, I have cheated. I had difficulty finding the start and end, given, let's say, the month 6. So I hardcoded the values in the QUARTER_RANGE constant. I want to be able to remove that QUARTER_RANGE constant and find the beginning and end (e.g. [4,6]) without it.
So for example, if the input 3 (March),6 (June),9(September),12(December) is passed, I will know its the end of the quarter, using modulus arithmetic:
3 % 3
=> 0
6 % 3
=> 0
9 % 3
=> 0
12 % 3
=> 0
But the tricky part is given let's say 5 (May), how can I return [4,6]
?
Upvotes: 0
Views: 66
Reputation: 110685
You could do the following:
MONTHS_PER_PERIOD = 3
PERIODS = (1..12).step(MONTHS_PER_PERIOD).map do |m|
m..(m+MONTHS_PER_PERIOD-1)
end
#=> [1..3, 4..6, 7..9, 10..12]
def month_to_period(m)
PERIODS.find { |p| p.cover?(m) }
end
(1..12).each { |m| puts month_to_period(m) }
1..3
1..3
1..3
4..6
4..6
4..6
7..9
7..9
7..9
10..12
10..12
10..12
MONTHS_PER_PERIOD = 2
PERIODS = (1..12).step(MONTHS_PER_PERIOD).map do |m|
m..(m+MONTHS_PER_PERIOD-1)
end
#=> [1..2, 3..4, 5..6, 7..8, 9..10, 11..12]
(1..12).each { |m| puts month_to_period(m) }
1..2
1..2
3..4
3..4
5..6
5..6
7..8
7..8
9..10
9..10
11..12
11..12
Upvotes: 0
Reputation: 80065
(1..12).each do |m|
low = 3*((m-1)/3) + 1
p m, [low, low+2]
end
result:
1
[1, 3]
2
[1, 3]
3
[1, 3]
4
[4, 6]
5
[4, 6]
6
...
Upvotes: 1
Reputation: 1490
Well, I'm not sure why you want it but if you want to use modulo this should work out how you want:
month = some_num
quarter_range = []
if month%3 == 0
# end of quarter
quarter_range = [month-2, month]
elsif month%3 == 1
# beginning of quarter
quarter_range = [month, month+2]
else
# middle of quarter
quarter_range = [month-1, month+1]
end
return quarter_range
Upvotes: 0
Reputation: 106027
You can get the start of the quarter like this:
def qtr_start(mon)
mon - (mon - 1) % MONTHS_PER_QUARTER
end
qtr_start(9) # => 7
The end of the quarter is just that plus two:
def qtr_end(mon)
qtr_start(mon) + 2
end
qtr_end(9) # => 9
Put them together:
def qtr_start_end(mon)
start = mon - (mon - 1) % MONTHS_PER_QUARTER
[ start, start + 2 ]
end
(1..12).each do |mon|
start_end = qtr_start_end(mon)
puts "Month #{mon} is in quarter #{start_end.inspect}"
end
# => Month 1 is in quarter [1, 3]
# Month 2 is in quarter [1, 3]
# Month 3 is in quarter [1, 3]
# Month 4 is in quarter [4, 6]
# Month 5 is in quarter [4, 6]
# Month 6 is in quarter [4, 6]
# Month 7 is in quarter [7, 9]
# Month 8 is in quarter [7, 9]
# Month 9 is in quarter [7, 9]
# Month 10 is in quarter [10, 12]
# Month 11 is in quarter [10, 12]
# Month 12 is in quarter [10, 12]
Upvotes: 1