我在美国,我们通常将日期格式化为“月/日/年”。我试图确保我的 Rails 应用程序(使用 Ruby 1.9)在任何地方都采用这种格式,并按照它在 Ruby 1.8 下的方式工作。
我知道很多人都有这个问题,所以我想在这里创建一个权威指南。
具体来说:
- “04/01/2011”是 2011 年 4 月 1 日,而不是 2011 年 1 月 4 日。
- “4/1/2011”也是 2011 年 4 月 1 日 - 不需要前导零。
我该怎么做?
这是我目前所拥有的。
控制 Date#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
方法目前看起来像这样 ( 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;
这个解决方案让我的测试通过了,但它疯了吗?我只是在某处缺少配置选项,还是有其他更简单的解决方案?
还有其他我没有涉及的日期解析案例吗?
最佳答案
gem :ruby-american_date
这个 gem 是在我问这个问题后创建的。我现在正在使用它并且很高兴。
关于ruby-on-rails - 如何使用 Ruby 1.9 在 Rails 中使用美式日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7286467/