Take the 2-minute tour ×

The problem

  1. I have a Ruby on Rails model with a Date attribute.
  2. In the form for this model, I am using a single text field with a JQuery datepicker to represent this attribute (not a drop down for each of year, month, and day, as is the Rails custom).
  3. The datepicker inserts dates with a mm/dd/yyyy format.
  4. Rails is expecting dates with a dd/mm/yyyy format.


  • If a user selects March 12th, 2012, the datepicker puts 03/12/2012, which is interpreted by Rails as December 3rd, 2012.
  • If a user selects March 20th, 2012, the datepicker puts 03/20/2012, which is interpreted by Rails as the 3rd day of the 20th month of 2012. Since this date doesn't exist, Rails casts this to a nil value (I think).


How do I change the date format Rails uses when parsing this date text field?


1) I do not want to change the format of the date the datepicker inserts into the text field,

2) I am not asking about displaying my date attribute in a view.

share|improve this question
add comment

5 Answers

up vote 7 down vote accepted

I initially thought this could be solved through the Rails internationalization features, but it turns out I was wrong.

Ever since Ruby 1.9, the standard format for date parsing is dd/mm/yyyy, so as to better accomodate international users. More details can be found in this SO answer.

That standard is maintained in Rails, as Date.parse is now used to process data from form inputs. Using a before_validation callback won't work because the field is going to be received as nil by the callback method.

Right now there are two gems dealing with this specific issue, namely that date parsing in Rails does not follow the locale settings from I18n.locale. Both seem to work well.

  1. delocalize, by clemens - Seems to have been applied successfully in a decent number or projects and has the highest number of stars at the moment.

  2. i18n_alchemy by carlosantoniodasilva - This one has been released more recently. The author is a Rails core team member, and a very active one at that. Definitely deserves a look.

share|improve this answer
Thank you for your answer. As far as I can tell, by using I18n, I can only change the way dates are displayed, not the way they are parsed by ActiveRecord. Am I missing something? –  toasterlovin Mar 25 '13 at 22:26
Actually in your case the Datepicker is responsible for filling in the date field, but Rails is going to parse that content according to the i18n settings. I have a project where I had to solve exactly that same problem. –  depa Mar 25 '13 at 22:40
More specifically, you want Rails to expect dates in a mm/dd/yyyy format. By using the correct locale setting and YAML file, you can do exactly that. –  depa Mar 25 '13 at 22:49
Quick tip: If you open a console and type I18n.locale you can see the current setting used by the app. –  depa Mar 25 '13 at 22:58
Hmmm, I must not be changing the right thing in the en.yml file. I changed en -> date -> formats -> default to be ! '%m/%d/%Y'. That changed the way dates were outputted, so I know localization is working, but it did not change the way dates were parsed. –  toasterlovin Mar 25 '13 at 23:17
show 8 more comments

Since you don't want to change the picker's format, I would suggest you use a hidden field for the actual model property.

For example, add a hidden field for the model's date property, assuming you use a form builder as usual:

f.hidden_field :date

Then for the picker text input, don't bind it to the model's date property. Let's say the hidden field has ID 'modelname_date' and the picker text input has ID 'date_picker', use the following to make it work:

  $("#date_picker").datepicker({altField: '#nodelname_date', altFormat: 'dd/mm/yyyy'});

In this way the date picker shows the date as 'mm/dd/yyyy' but Rails will see the date as 'dd/mm/yyyy'.


If you want to work this out on the Rails side, here's another solution I'd suggest:

  • Add a virtual property to your model: attr_accessor :bad_format_date
  • Add a before_validation callback in which you parse the input date and assign it to the real field:
before_validation do
  self.date = Date.strptime(bad_format_date, "%m/%d/%Y")

Then for the form on the view use bad_format_date but initialize it with the date field value (if it's an edit form).

share|improve this answer
This seems like a roundabout way to get where I'm trying to go. I would really like to do this on the Rails side. Is there no way to do that? –  toasterlovin Mar 25 '13 at 22:23
I see your point. Added a solution on the Rails side. –  James Chen Mar 26 '13 at 0:34
Do you know if it's possible to accomplish this without a virtual attribute on the model? I ask because it seems like a heavy weight solution to simply changing the date format being parsed. In doing some playing around in my Rails console, I believe that ActiveRecord is using Date.parse to do the date parsing, but can't find documentation to confirm my hunch. Was wondering if you knew? I'm probably going to award the bounty to your answer, but I would really like to provide future visitors with the Why this is the best way to accomplish this, not just the How. –  toasterlovin Mar 29 '13 at 16:26
add comment

The timeliness gem makes ruby date/time parsing much more customizeable and integrates well with Rails.

Since you're working with Rails, be sure to check out the validates_timeliness project as well by the same guy. It includes all of timeliness plus sophisticated date/time validation methods for ActiveModel.

share|improve this answer
add comment

You could try do something like this.

 $('#date_picker').datepicker( {
      beforeShowDay: $.datepicker.noWeekends, 
      showOtherMonths: true,
      selectOtherMonths: true,
      dateFormat: 'dd-mm-yy',
      defaultDate: date,
      gotoCurrent: true

share|improve this answer
Thank you for the answer, but I specifically mentioned that I am not looking to change the format that the datepicker inserts into the text field. –  toasterlovin Mar 25 '13 at 22:21
add comment

I just add the following monkey patch to config/time_formats.rb

class Date
  class << self
    alias :euro_parse :_parse
    def _parse(str,comp=false)
      str = str.to_s.strip
      if str == ''
      elsif str =~ /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{2,4})/
        year,month,day = $3.to_i,$1,$2
        date,*rest = str.split(' ')
        year += (year < 35 ? 2000 : 1900) if year < 100
        euro_parse("#{year}-#{month}-#{day} #{rest.join(' ')}",comp)
share|improve this answer
add comment

Your Answer


