开发者

How to make US date format as the default when saving to a model in Rails 3

The US date used to be accepted/parsed correctly, but not anymore in Rails 3. The %Y-%m-%d is accepted but not %m/%d/%Y.

g = Grant.new
g.budget_begin_date = '12/31/2010'
#g.budget_begin_date returns nil
g.budget_begin_date = '2010-12-31'
#g.budget_begin_date returns Fri, 31 Dec 2010 00:00开发者_运维问答:00 UTC +00:00


As of Ruby 1.9, Date.parse stopped handling the ambiguous format mm/dd/yyyy (american format) or dd/mm/yyyy (rest of civilized world format).

The american_date gem linked here makes the assumption older Ruby did, and can thus parse an american date as expected.


Your code example doesn't quite show Date.parse failing to interpret US style dates, but you're right, it doesn't. Instead of this:

Date.parse("12/31/2010")

Use this:

Date.strptime("12/31/2010", "%m/%d/%Y")


If you are not averse to using a gem, you can check out the Chronic gem: https://github.com/mojombo/chronic

You can have Chronic parse your begin date before saving the model.


The Date class calls self.parse method to parse the provided string to date.

1.9.2p320 :051 > x = Date.parse('2011-31-12')
ArgumentError: invalid date
from .../rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/date.rb:1022:in `new_by_frags'
from .../rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/date.rb:1066:in `parse'

which is turn calls a self method "_parse" which is located in the file ".../ruby-1.9.2-p320/lib/ruby/1.9.1/date/format.rb".

it calls the strftime function("def strftime(fmt='%F')") where the default format for date formating is "%F" which according to the Time class documentation is " %F - The ISO 8601 date format (%Y-%m-%d)".


In modern ruby (ie. with prepend) you can insert your own type casting in front of Rails's. You'll want to do this for whatever other date/time formats you're using. Here's the code for Date, just stick this in an config/initializers/typecasts.rb or somewhere:

module Typecasting
  module Date
    def cast_value v
      ::Date.strptime v, "%m/%d/%Y" rescue super
    end  
  end  

  ::ActiveRecord::Type::Date.prepend Date
end

Rails will try the American format and fall back to using the builtin method if that didn't work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜