生成Ruby / Rails中两个日期之间的商业周列表

时间:2015-04-10 13:56:08

标签: ruby-on-rails ruby date week-number

我正在尝试创建一个年周列表(相当于mySQL的YEARWEEK(date,1))落在Rails中的两个日期值之间。如果开始日期和结束日期在同一年下降,则列表正在完美生成。是我的代码:

  campaign_start_date = "2013-08-02 06:59:00"
  campaing_end_date = "2013-09-01 06:59:00"

  start_year = DateTime.parse(campaign_start_date).cwyear
  start_week = "%04d%02d" % [start_year, DateTime.parse(campaign_start_date).cweek]

  end_year = DateTime.parse(campaing_end_date).cwyear
  end_week = "%04d%02d" % [end_year, DateTime.parse(campaing_end_date).cweek]

  if start_year == end_year
    (start_week..end_week).each{ |i| result << i }
  else
    # need to build a suitable logic here. to handle the case when duration spans over multiple years. for example started in 01-Nov-14 and ended in 01-May-15
  end

  return result

上面的日期值没有问题,如果是这样的话,我会得到的结果是:

[
  "201331",
  "201332",
  "201332",
  "201333",
  "201334",
  "201335"
]

这也是我想要的。但是,如果我的开始日期和结束日期值是这些,例如:

  campaign_start_date = "2014-07-23 06:59:00"
  campaing_end_date = "2015-03-01 06:59:00"

意味着在不同年份下降,然后它需要与我在if条件中具有的逻辑不同,因为对于这些日期值(start_week=201430end_week=201509if条件不适合此处,因为它会生成80值,这是错误的,因为这些日期之间的周数不是80。需要帮助来开发else案例的逻辑。可能很容易,但现在我只是厌倦了深入挖掘它。

特别关注:解决方案应关注商业年度和商业周(参见.cwyear和.cweek铁路功能)例如,2016-01-01的年周将是201553不是201601

在这方面的任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:1)

感谢那些回复的人。我终于解决了这个问题:

  campaign_weeks = []

  campaign_start_date = "2014-07-23 06:59:00" # or any date
  campaing_end_date = "2015-03-01 06:59:00" # or any date

  start_year = DateTime.parse(campaign_start_date).cwyear
  start_cweek_of_the_campaign = "%04d%02d" % [start_year, DateTime.parse(campaign_start_date).cweek]

  end_year = DateTime.parse(campaing_end_date).cwyear
  end_cweek_of_the_campaign = "%04d%02d" % [end_year, DateTime.parse(campaing_end_date).cweek]

  if start_year == end_year
    (start_cweek_of_the_campaign..end_cweek_of_the_campaign).each do |w|
      campaign_weeks << ("%04d%02d" % [start_year, w])
    end
  else
    (start_year..end_year).each do |y|
      first_cweek_number_of_the_year = (y == start_year) ? start_cweek_of_the_campaign : 1
      last_cweek_number_of_the_year = (y == end_year) ? end_cweek_of_the_campaign : DateTime.new(y, 12, 28).cweek
      (first_cweek_number_of_the_year .. last_cweek_number_of_the_year).each do |w|
        campaign_weeks << ("%04d%02d" % [y, w])
      end
    end
  end

  return campaign_weeks

注意:12月28日总是落在今年的最后一个cweek / iso周。今年的最后一个ISO周是52或53。

参考:http://en.wikipedia.org/wiki/ISO_week_date#Last_week

从这个答案中得到一些提示:Calculating the number of weeks in a year with Ruby

答案 1 :(得分:0)

瓶颈是(start_week..end_week)范围。它显然经历了一百(因为我们是小数):

 2014xx ⇒ 201452 ⇒ 201453 ⇒ ... ⇒ 201499 ⇒ 201500 ⇒ ...

您应该过滤您的范围,例如:

r = (start_week..end_week)
r.to_a.reject { |e| e[-2..-1].to_i > 52 }

根据您计算周数的方式(= - 基于或基于1),201500也应该被过滤:/

r.to_a.select { |e| e[-2..-1].to_i.between? 1, 52 }

答案 2 :(得分:0)

试试这个;它适用于任何一组日期,无论年份是否相同:

campaign_start_date = "2014-07-23 06:59:00"
campaign_end_date = "2015-03-01 06:59:00"

start_date = DateTime.parse(campaign_start_date)
end_date = DateTime.parse(campaign_end_date)

while start_date < end_date
  puts "%04d%02d" % [start_date.cw_year, start_date.cweek]
  start_date = start_date + 7.days
end

答案 3 :(得分:0)

讨论有点晚了,但这里是我用来获得两个日期之间的商业周数:

def cweek_diff(start_date, end_date)
  return if end_date < start_date
  cweek_diff = (end_date.cweek - start_date.cweek) + 1
  cwyear_diff = end_date.cwyear - start_date.cwyear
  cyear_diff * 53 + cweek_diff - cwyear_diff
end

在我的案例中它完美无缺。希望它有所帮助;)