chronic自然语言来表达时间

May 07, 2011

最近的Rails项目的cucumber测试中,经常会碰到需要处理时间。有意思的是,我们在cucumber测试中需要尽量用自然语言来表达时间,而在其对应的step definition中需要解析成为对应的时间。 比如我们需要在feature表达“3个月以前”这个概念,原有的做法是 直接在feature中写成"3.months.ago" ,而对应的步定义中则是用到eval()来解析成为对应的时间:eval(time_literal || "1.month.ago").  也许这个"3.months.ago"还不是非常接近自然语言,为什么中间有"."了? 所以我们可以进一步改进一下, 在feature中写成"3 months ago" ,然后在调用eval函数之前,先将空格替换成点。 嗯, 还不错,至少Rails自带支持的时间处理是够用的。 但是后来我们需要处理“上个星期的周二”, 那这个Rails自带的时间支持无法很好的完成任务了。

所以也就出现了chronic这个gem.
Chronic is a natural language date/time parser written in pure Ruby. See below for the wide variety of formats Chronic will parse.
Chronic能非常的适用于上述的情景。 下面摘抄了chronic上的一些例子:
  
  3 years ago
  5 months before now
  7 hours ago
  7 days from now
  1 week hence
  in 3 hours
  1 year ago tomorrow
  3 months ago saturday at 5:00 pm
  7 hours before tomorrow at noon
  3rd wednesday in november
  3rd month next year
  3rd thursday this september
  4th day last week

我们可以直接在feature中写“last week tuesday" ,然后在步定义中直接调用 Chronic.parse(time_literal)就可以很方便的得到我们需要的时间。 参考: Chronic 0.3.0 Released: Improved Natural Language Date/Time Parsing

更新: 2010/06/19 Chronic之前用的是2.0.3版本,存在一个问题, 比如说今天是2011/05/30, 使用Chronic.parse("3 months ago") 会得到2011/03/02( 简单的就是减去90天), 而不是像Rails内制的 3.months.ago得到2011/02/28. 我有在github isssue发过一个贴子Parse n months ago problem,得到作者的回复是,在Chronic 0.4.0版本以后都统一使用了ruby自制的时间处理. Ruby 5也贴出了关于chronic更新的消息 chronic update