获取当前季度的月份数字

问题描述

| 我需要一个数组,其中包含本季度的月份数。我想提供
Date.today
,然后得到例如。
[1,2,3]
。 我如何以最简单的方式做到这一点? (不使用
switch
/
case
)。     

解决方法

        
def quarter_month_numbers(date)
  quarters = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
  quarters[(date.month - 1) / 3]
end
    ,        
def quarter(date)
  1 + ((date.month-1)/3).to_i
end
    ,        我建议构建一个按月索引的哈希,如下所示:
@quarters_by_month = Hash[(1..12).map {|v| i=((v-1)/3)*3; [v,[i+1,i+2,i+3]]}]
那么将来的任何查找都只是
@quarters_by_month[month]
由于@ x3ro提到了CPU时间,因此我认为对所有建议的解决方案(包括OP想要排除的
case
语句)进行基准测试会很有趣。结果如下:
> 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)
这是代码:
def case_statement(month)
  case month
  when 1,3
    [1,3]
  when 4,6
    [4,6]
  when 7,9
    [7,9]
  when 10,12
    [10,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+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,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+3]]}]

    for i in 1..n do
      defined_hash(rand(11) + 1)
    end
  end
end
    ,        解决方案1
(((Date.today.month - 1) / 3) * 3).instance_eval{|i| [i+1,i+3]}
解决方案2
[*1..12][((Date.today.month - 1) / 3) * 3,3]
    ,        您可以执行以下操作:
m = date.beginning_of_quarter.month
[m,m+1,m+2]
在irb中显示如下:
>> date=Date.parse \"27-02-2011\"
=> Sun,27 Feb 2011  
>> m = date.beginning_of_quarter.month
=> 1
>> [m,m+2]
=> [1,3]
我不知道这与其他方法相比有多快,也许@Wes也可以用这种方法进行基准测试。 我认为这种方法的优点之一是代码清晰。它不复杂。     ,        看看这个小片段:
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
    ,        对于
Array
month    = Date.today.month # 6
quarters = [[1,12]]
quarters.select { |quarter| quarter.include?(month) }
=> [[4,6]]
Hash
month    = Date.today.month # 6
quarters = {
  [1,3]    => \'First  quarter\',6]    => \'Second quarter\',9]    => \'Third  quarter\',12] => \'Fourth quarter\',}
quarters.select { |quarter| quarter.include?(month) }
=> {[4,6]=>\"Second quarter\"}
希望它有所帮助;)