【问题标题】:Why is Chronic incorrectly parsing for four letter months?为什么 Chronic 会错误地解析四个字母月?
【发布时间】:2013-06-14 17:46:11
【问题描述】:

在 Chronic 0.9.1 中,在解析 Febr 2013 时,我得到了一个结果 June 2013Feb 2013 解析得很好,但 Febr 2013 不是。

我认为问题在于月份缩写有四个字母。

我需要:

  • Febr 2013解析为February 2013,或
  • 使Febr 2013无效。

验证我使用的日期:

Chronic.parse(params[:date]).blank?

这是一个错误吗?我可以做周围的工作吗?或者,是否有正确的方法来验证这一点?

【问题讨论】:

  • 感谢编辑:)

标签: ruby-on-rails ruby chronic


【解决方案1】:

从技术上讲,这是一个错误,但我更倾向于将其称为逻辑漏洞。以下是Chronic::Repeater.scan_for_month_names 决定月份的方式:

# File 'lib/chronic/repeater.rb', line 38

def self.scan_for_month_names(token)
  scan_for token, RepeaterMonthName,
  {
    /^jan[:\.]?(uary)?$/ => :january,
    /^feb[:\.]?(ruary)?$/ => :february,
    /^mar[:\.]?(ch)?$/ => :march,
    /^apr[:\.]?(il)?$/ => :april,
    /^may$/ => :may,
    /^jun[:\.]?e?$/ => :june,
    /^jul[:\.]?y?$/ => :july,
    /^aug[:\.]?(ust)?$/ => :august,
    /^sep[:\.]?(t[:\.]?|tember)?$/ => :september,
    /^oct[:\.]?(ober)?$/ => :october,
    /^nov[:\.]?(ember)?$/ => :november,
    /^dec[:\.]?(ember)?$/ => :december
  }
end

月份名称可以是三个字母,也可以是整个名称。

您可以从源中提取该方法,修改模式以满足您的需求,然后覆盖该方法,并将其作为补丁提交,以便将调整添加到 gem 的未来修订版中。或者,您可以通过搜索单词开头的三字母缩写并修剪无关字符来修改传入的字符串。


好的,这里有一些值得细细琢磨的东西:

require 'abbrev'

MONTHS = %w[
  january
  february
  march
  april
  may
  june
  july
  august
  september
  october
  november
  december
]

MONTHS_ABBREV = Abbrev.abbrev(MONTHS)
MONTHS_REGEX = /\b(?:j(?:a(?:n(?:u(?:a(?:ry?)?)?)?)?|u(?:ly?|ne?))|s(?:e(?:p(?:t(?:e(?:m(?:b(?:er?)?)?)?)?)?)?)?|a(?:u(?:g(?:u(?:st?)?)?)?|p(?:r(?:il?)?)?)|d(?:e(?:c(?:e(?:m(?:b(?:er?)?)?)?)?)?)?|f(?:e(?:b(?:r(?:u(?:a(?:ry?)?)?)?)?)?)?|n(?:o(?:v(?:e(?:m(?:b(?:er?)?)?)?)?)?)?|o(?:c(?:t(?:o(?:b(?:er?)?)?)?)?)?|ma(?:r(?:ch?)?|y))\b/i

%w[j ja jan janu january f fe feb febr february].each do |m|
  puts "#{ m } => #{ MONTHS_ABBREV[m[MONTHS_REGEX]] }" 
end

哪些输出:

j =>
ja => january
jan => january
janu => january
january => january
f => february
fe => february
feb => february
febr => february
february => february

换句话说,j 不是唯一的,所以没有命中。 ja 是唯一的,并且与 january 相关联,ja... 测试的其余部分也是如此。 f 是独一无二的,所以它会命中,就像所有其余的 f... 测试一样。

Abbrev.abbrev 是做什么的?它将传入的单词分解为用于标识整个单词的最小唯一字符串。如果我只使用四个月,情况如下:

require 'abbrev'

MONTHS = %w[
  march
  may
  june
  july
]

MONTHS_ABBREV = Abbrev.abbrev(MONTHS)
pp MONTHS_ABBREV

导致:

{"marc"=>"march",
 "mar"=>"march",
 "jun"=>"june",
 "jul"=>"july",
 "march"=>"march",
 "may"=>"may",
 "june"=>"june",
 "july"=>"july"}

这些为正则表达式创造了美妙的种子值。

我从哪里得到MONTHS_REGEX?嘿...这是一些神奇的 Perl 代码,它使用了一个鲜为人知的模块 Regexp::Assemble,我在 Ruby 中非常想念它。它很恶心......不,它......非常好,并且与 Perl 的工作方式密切相关,当我阅读它时让我头疼,否则我会移植它。

【讨论】:

  • 我要实现这个,我会接受答案!真的谢谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-15
  • 1970-01-01
相关资源
最近更新 更多