如何使用Ruby 1.9在Rails中使用美式日期?

我在美国,我们通常将日期格式设置为“月/日/年”。 我正在努力确保使用Ruby 1.9的Rails应用程序在任何地方都采用这种格式,并按照它在Ruby 1.8下的方式工作。

我知道很多人都有这个问题,所以我想在这里创建一个明确的指南。

特别:

  1. ’04 / 01/2011’是2011年4月1日,而不是2011年1月4日。
  2. ‘2011年4月1日’也是2011年4月1日 – 不需要领先的零。

我怎样才能做到这一点?

这是我到目前为止所拥有的。

控制日期#to_s行为

我在application.rb有这一行:

  # Format our dates like "12/25/2011' Date::DATE_FORMATS[:default] = '%m/%d/%Y' 

这确保了如果我执行以下操作:

 d = Date.new(2011,4,1) d.to_s 

……我得到“04/01/2011”,而不是“2011-04-01”。

控制String#to_date行为

ActiveSupport的String#to_date方法目前看起来像这样( 源代码 ):

  def to_date return nil if self.blank? ::Date.new(*::Date._parse(self, false).values_at(:year, :mon, :mday)) end 

(如果你不遵循这个,第二行创建一个新的日期,按年顺序传递年,月和日。它获取年,月和日值的方式是使用Date._parse ,它解析一个字符串,然后以某种方式决定这些值是什么,然后返回一个散列.values_at按照Date.new想要它们的顺序从该散列中拉出值。)

因为我知道我通常会传递像“04/01/2011”或“4/1/2011”这样的字符串,所以我可以通过monkeypatching来解决这个问题:

 class String # Keep a pointer to ActiveSupport's String#to_date alias_method :old_to_date, :to_date # Redefine it as follows def to_date return nil if self.blank? begin # Start by assuming the values are in this order, separated by / month, day, year = self.split('/').map(&:to_i) ::Date.new(year, month, day) rescue # If this fails - like for "April 4, 2011" - fall back to original behavior begin old_to_date rescue NoMethodError => e # Stupid, unhelpful error from the bowels of Ruby date-parsing code if e.message == "undefined method `<' for nil:NilClass" raise InvalidDateError.new("#{self} is not a valid date") else raise e end end end end end class InvalidDateError < StandardError; end; 

这个解决方案让我的测试通过,但是它疯了吗? 我只是在某个地方缺少配置选项,还是有其他更简单的解决方案?

有没有其他日期解析案例我没有涉及?

gem:ruby-american_date

这个gem是在我问这个问题后创建的。 我现在正在使用它并且很高兴。

https://github.com/jeremyevans/ruby-american_date

Date.strptime可能就是你在ruby 1.9中寻找的东西。

你可能暂时将它monkeypatching到string.to_date,但strptime是解析ruby 1.9中的字符串日期的最佳解决方案。

此外,据我所知,格式与strftime对称。

你可以使用rails-i18n gem或只是复制en-US.yml并在config / application.rb中设置你的默认语言环境“en-US”

要解析美式日期,您可以使用:

 Date.strptime(date_string, '%m/%d/%Y') 

在控制台中:

 > Date.strptime('04/01/2011', '%m/%d/%Y') => Fri, 01 Apr 2011 > Date.strptime('4/1/2011', '%m/%d/%Y') => Fri, 01 Apr 2011 

使用REE? :d

说真的。 如果这是一个小应用程序,您可以完全控制或者您正在标准化该日期格式,猴子修补项目是完全合理的。 您只需确保所有输入都以正确的格式输入,无论是通过API还是网站。

而不是使用to_s for Date实例,养成使用strftime的习惯。 它需要一个格式字符串,使您可以完全控制日期格式。

编辑:strptime通过指定格式字符串使您可以完全控制解析。 您可以在两种方法中使用相同的格式字符串。

另一种选择是慢性病 – http://chronic.rubyforge.org/

您只需将endian首选项设置为仅强制使用MM / DD / YYYY日期格式:

 Chronic::DEFAULT_OPTIONS[ :endian_precedence ] = [ :middle ] 

但是,Chronic的默认值是无序的美国日期格式!