My user wants to use the date format %d/%m/%Y (eg: 26/02/2011).
In order to correctly display dates, I therefore changed to :default format in environment.rb:
environment.rb :
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(
:default => "%d/%m/%Y"
)
It's working fine but I have one problem when trying to save date strings entered in this format in the database.
Rails seems to take the strings as formated with %m/%d/%Y instead of %d/%m/%Y
04/02/2011 is saved as 2011-04-02 and 26/02/2011 is simply invalid and not saved...
I searched for solutions for this but the ones I found rely on reformating the dates in my models such as the one below :
mymodel.rb :
def datefield_formatted
datefield.strftime '%m/%d/%Y'
end
def datefield_formatted=(value)
self.datefield = Time.parse(value)
end
view.html.erb :
<%= form.input :datefield_formatted %>
I could use this solution but it will require a change in my models for every 'datefield' (there are many in my apps).
I was therefore wondering if there is a was to tell Rails to correctly 'read' string as %d/%m/%Y when converting and saving to the database.
I think the best would be to save the dates in the usual sql format (i.e. date fields not varchar) and only to show them in the %d/%m/%Y. For that I usually use the localization files and l(date) function. e.g. this in localization file
date:
formats:
default: "%d/%m/%Y"
and this wherever you use the date in views
l(date)
Another idea is to overload the activerecord how it saves dates, but this is a bit of overkill :/
I eventually found a solution searching more deeply into Stackoverlow :
This blog post explains the problem and gives a working solution : http://blog.nominet.org.uk/tech/2007/06/14/date-and-time-formating-issues-in-ruby-on-rails/
So we have : lib/column-patch.rb
class ActiveRecord::ConnectionAdapters::Column
def self.string_to_date(string)
return string unless string.is_a?(String)
begin
return DateTime.strptime(string, ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS[:default])
rescue
date_array = ParseDate.parsedate(string)
# treat 0000-00-00 as nil
Date.new(date_array[0], date_array[1], date_array[2]) rescue nil
end
end
def self.string_to_time(string)
return string unless string.is_a?(String)
begin
if dt=Date._strptime(string,ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS[:default])
return Time.mktime(*dt.values_at(:year, :mon, :mday, :hour, :min, :sec, :zone, :wday))
else
raise "Bad format"
end
rescue
time_hash = Date._parse(string)
time_hash[:sec_fraction] = microseconds(time_hash)
time_array = time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction)
# treat 0000-00-00 00:00:00 as nil
Time.send(ActiveRecord::Base.default_timezone, *time_array) rescue DateTime.new(*time_array[0..5]) rescue nil
end
end
end
And we add in config/environment.rb
require 'column-patch'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With