1

我正在尝试将“Sep 11, Oct 31, Feb 28”之类的字符串转换为 DateTime 实例,作为屏幕抓取工具的一部分。使用 DateTime.parse() 可以正常工作,除了数据跨越年份,而且它天真地(并且可能正确地)返回当前年份的日期。

例如下面的测试用例。

test "dateA convert next year" do
  TimeService.stubs(:now).returns(Time.new(2013, 12, 30, 9, 30))
  assert_equal(Date.new(2014, 1, 2), Extraction.dateA("Jan 2"))
end

我更新了我的方法以查看年份 + 1 的日期,并返回最接近“现在”的日期 - 这很好用。但是感觉有点难看,我正在寻找一个更优雅的解决方案。

def Extraction.dateA(content)
  return_value = DateTime.parse(content)
  next_year = return_value.change(:year => return_value.year + 1)
  now = TimeService.now.to_i
  if (next_year.to_i - now).abs < (return_value.to_i - now).abs then
    return_value = next_year
  end
  return_value
end
  • TimeService.now 只是一个返回当前时间以帮助存根的实用程序。
  • 对不起,我的红宝石,我是新手。
4

1 回答 1

1

我认为这可以按预期工作,也允许上一年最接近的日期:

module Extraction
  def Extraction.date_a(content)
    parsed_date = DateTime.parse(content)
    now = DateTime.now
    dates = [ parsed_date, parsed_date.next_year, parsed_date.prev_year ]
    dates.min_by { |d| ( d - now ).abs }
  end
end

几点:

  • 将方法名称更改为date_a,只是一个不同于 Java 的 Ruby 约定。
  • 我使用了一些内置方法next_yearprev_yearDateTime
  • 我使用了一个时差度量,并从三个候选日期中选择了具有最小值的日期(这就是这样min_by做的)。这是比条件切换更简单的代码,尤其是要考虑三个日期。

原来我忘记了min_by,我不经常使用它,但它非常适合这个问题。

请注意,有一个病态案例 - “2 月 29 日”。如果它在文本中正确显示,则根据其性质,它将定义哪一年是有效的,并且如果当前年份是例如 2015 年,它将不会解析。

于 2013-09-15T07:58:26.617 回答