Get month numbers for the current quarter

I need an array with numbers for months in the current quarter. I want to put Date.today and then get, for example. [1,2,3] .

How do I do this in the easiest way? ( Not using switch / case ).

+6
source share
7 answers
 def quarter_month_numbers(date) quarters = [[1,2,3], [4,5,6], [7,8,9], [10,11,12]] quarters[(date.month - 1) / 3] end 
+4
source
 def quarter(date) 1 + ((date.month-1)/3).to_i end 
+4
source

I would suggest creating a monthly indexed hash like this:

 @quarters_by_month = Hash[(1..12).map {|v| i=((v-1)/3)*3; [v,[i+1, i+2, i+3]]}] 

then any future search is just

 @quarters_by_month[month] 

Since @ x3ro mentions CPU time, I thought it would be interesting to evaluate all the proposed solutions, including the case , which the OP wanted to exclude. Here are the results:

 > ruby jeebus.rb user system total real case_statement: 0.470000 0.000000 0.470000 ( 0.469372) quarter_month: 0.420000 0.000000 0.420000 ( 0.420217) solution1: 0.740000 0.000000 0.740000 ( 0.733669) solution2: 1.630000 0.010000 1.640000 ( 1.634004) defined_hash: 0.470000 0.000000 0.470000 ( 0.469814) 

Here is the code:

 def case_statement(month) case month when 1,2,3 [1,2,3] when 4,5,6 [4,5,6] when 7,8,9 [7,8,9] when 10,11,12 [10,11,12] else raise ArgumentError end end def defined_hash(month) @quarters_by_month[month] end def solution1(month) (((month - 1) / 3) * 3).instance_eval{|i| [i+1, i+2, i+3]} end def solution2(month) [*1..12][((month - 1) / 3) * 3, 3] end def quarter_month_numbers(month) @quarters[(month - 1) / 3] end require 'benchmark' n = 1e6 Benchmark.bm(15) do |x| x.report('case_statement:') do for i in 1..n do case_statement(rand(11) + 1) end end x.report('quarter_month:') do @quarters = [[1,2,3], [4,5,6], [7,8,9], [10,11,12]] for i in 1..n do quarter_month_numbers(rand(11) + 1) end end x.report('solution1:') do for i in 1..n do solution1(rand(11) + 1) end end x.report('solution2:') do for i in 1..n do solution2(rand(11) + 1) end end x.report('defined_hash:') do @quarters_by_month = Hash[(1..12).map {|v| i=((v-1)/3)*3; [v,[i+1, i+2, i+3]]}] for i in 1..n do defined_hash(rand(11) + 1) end end end 
+2
source

Solution 1

 (((Date.today.month - 1) / 3) * 3).instance_eval{|i| [i+1, i+2, i+3]} 

Decision 2

 [*1..12][((Date.today.month - 1) / 3) * 3, 3] 
+1
source

Take a look at this little snippet:

 months = (1..12).to_a result = months.map do |m| quarter = (m.to_f / 3).ceil ((quarter-1)*3+1..quarter*3).to_a end puts result.inspect 
0
source

You can do the following:

 m = date.beginning_of_quarter.month [m, m+1, m+2] 

Demonstrated below in irb:

 >> date=Date.parse "27-02-2011" => Sun, 27 Feb 2011 >> m = date.beginning_of_quarter.month => 1 >> [m, m+1, m+2] => [1, 2, 3] 

I don't know how quickly this compares with other methods, maybe @Wes can kindly compare this way.

One of the advantages of this approach is code clarity. This is not collapsed.

0
source

For Array

 month = Date.today.month # 6 quarters = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]] quarters.select { |quarter| quarter.include?(month) } => [[4, 5, 6]] 

For Hash

 month = Date.today.month # 6 quarters = { [1, 2, 3] => 'First quarter', [4, 5, 6] => 'Second quarter', [7, 8, 9] => 'Third quarter', [10, 11, 12] => 'Fourth quarter', } quarters.select { |quarter| quarter.include?(month) } => {[4, 5, 6]=>"Second quarter"} 

Wish it helps;)

0
source

Source: https://habr.com/ru/post/890339/


All Articles