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.
精彩评论