我在美国,我们通常将日期格式设置为“月/日/年”.我试图确保使用
Ruby 1.9的Rails应用程序在任何地方都采用这种格式,并且使用Ruby 1.8下的方式.
我知道很多人都有这个问题,所以我想在这里创建一个明确的指南.
特别:
>’04/01/2011’是2011年4月1日,而不是2011年1月4日.
>’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”.
控制字符串#to_date行为
ActiveSupport的String#to_date方法目前看起来像这样(source):
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;
这个解决方案使我的测试通过,但是它是疯狂的吗?我刚刚在某个地方缺少配置选项,还是有其他更容易的解决方案?
有没有其他日期解析案例我没有覆盖?
解决方法
宝石:ruby-american_date
自从我问这个问题以来,这个宝石是创造的.我现在正在使用它,并且很高兴.