Validating date formats in rails - ruby-on-rails

My simple date validation regex is not working correctly...
validates_format_of :dob, :with => /\d{2}\/\d{2}\/\d{4}/, :message => "^Date must be in the following format: mm/dd/yyyy"
What am I missing here? I'm trying to validate that a date is in the following format: mm/dd/yyyy - When I enter what should be valid data, I still get the error message.
Thanks for the help so far. Here's a snippet of code from my form that is passing the dob value in:
<tr>
<td>
<%= f.label :dob, "Date of Birth: " %>
</td>
<td>
<%= calendar_date_select_tag "user[dob]", "", :format => :american, :year_range => 50.years.ago..0.years.ago %>
</td>
</tr>
I think it may have something to do with my use of this js calendar plugin. A related problem is that my dob value is not maintained in the field if the post fails validation - the previously entered date value clears out...
Thanks!
Tom

You are probably using a string field to store a date. Consequently, any helpers that expect a DateTime or Time value will not work properly. You will need to investigate multiparameter assignments in Rails to figure out the proper way to do what you want to do (multiparemeter assignments is the magic behind sending 4 fields to Rails and get them converted to a DateTime or Time object).
In other words: if you are using a true DateTime field (as you should for this case) the validates_format_of will not have any effect (or will have adverse effects)

Found an excellent gem / plugin for all your date / time validations.
validates_timeliness
http://github.com/adzap/validates_timeliness

I've not tested your code within a Rails app, but your regular expression looks good to me. Try this test program:
#!/usr/bin/ruby
str = '08/24/2009'
regex = /\d{2}\/\d{2}\/\d{4}/
if str =~ regex
print 'matched', "\n"
else
print 'did not match', "\n"
end
Your regular expression matches. That suggests the problem is elsewhere.
You also might think about trying more general solutions for parsing a date in Ruby, such as the Date.parse method of the Date class. This does a little bit more validation than your regular expression, and it also provides some useful methods for converting dates between different formats.

Ahhh! Forcing date formats on the end-user when Rails implicitly converts them is a bad thing for usability, along with being more work for you (as you've seen).
If you've got a date/time attribute in your model, Rails will do its best to convert via Date.Parse (http://www.ruby-doc.org/core/classes/Date.html#M000644), e.g.
u = Somemodel.find :first
u.created_at
=> Tue Nov 20 15:44:18 -0500 2007
u.created_at = '2008/07/03'
=> "2008/07/03"
u.created_at
=> Thu Jul 03 00:00:00 -0400 2008
u.created_at = '05/10/1980'
=> "05/10/1980"
u.created_at
=> Sat May 10 00:00:00 -0400 1980

The regex looks correct to me. A useful resource is http://www.rubyxp.com/, which will test your regular expression against a given string. Indeed, the regex you have matches a date I typed into rubyxp.
Perhaps there's an issue in getting the entered data -- any chance the field is really called da?
Another item you may find useful: validates_timeliness, a rails plugin to validate dates and times. Why just validate the date format when you can check if it's a real date -- after all, 99/99/9999 will validate against your regex, but you may not really want to accept that.

You can try using current date to convert it into a format something like his:
def validate_date_format(value)
current_date = DateTime.now
begin
DateTime.strptime(current_date, value)
rescue
raise 'Invalid Format'
end
end

You might also want to look into the Chronic Gem (http://chronic.rubyforge.org/) which does natural date parsing. So you can enter in :
Next tuesday at 9pm
And it will interpret it correctly.

Related

Rails enforce a DateTime offset with a timezone param and DST

I just had a problem with a DateTime field that was submitted with the wrong timezone offset that I usually observe for people submitting from the same country (how surprising .... coming from an Internet Explorer). I am wondering if this may be linked with DST that will end soon at the end of october, and that some browser might have problems with that (although the affected DateTime was around the 15th of October, before the change).
The frontend form was using bootstrap datetimepicker (whose underlying implementation rely on momentJS). Here's a small extract of the JS that activates the picker and the field, although I'm not sure it's relevant here
<div class="col-xs-4" id="appointment-time-start">
<%= f.hidden_field :from %>
</div>
<script>
$('#appointment-time-start').datetimepicker({
format: 'LT',
defaultDate: "<%= model.from || (Time.now + 2.days) %>",
});
</script>
In order to avoid this issue, I am asking the user to also submit a timezone whose default is set to Paris timezone.
f.time_zone_select(:time_zone)
How should I use this timezone to modify the other dates that are sent as params ? I have a simple appointment form that sends two datetimes, and I need to modify them to ensure their offset matches the time_zone param (AND the Daylight Saving Time extra +1 if it is in effect).
I am also wondering if I should do this in the controller, or directly in the model. My controller is doing the usual thing and my current model looks like (but right now I'm not doing anything with time_zone)
class Appointment
include Mongoid::Document
field :from, type: DateTime
field :to, type: DateTime
field :time_zone, default: 'Paris'
Well I found this answer on a similar question... I'm surprised that there isn't a simpler helper that does that oO
def set_in_timezone(time, zone)
Time.use_zone(zone) { time.to_datetime.change(offset: Time.zone.now.strftime("%z")) }
end
Note that it still doesn't answer my question about whether I should do it in the model/controller.

Rails regex: validates_format_for date format with two different separators

I want to validate European date formats like "10.02.2012" or "10-02-2012" in my model.
Therefore I am using this line:
validates_format_of :matchdate, :with => /\A\d{2}(\.|-)\d{2}(\.|-)\d{4}\Z/i, :message => "Date incorrect"
The regex must be right, but whatever I type in, it always returns "Date incorrect".
I get the input from a form where I use
<%= f.text_field :matchdate, :size => '10' %>
together with the Datepicker UI, that outputs the right format. (I want to use both "." and "-" seperators, cause I collect the date in another scope, where both versions should be allowed.)
The params look correct as well, there it says: "...matchdate"=>"29.09.2012"
What am I doing wrong?
When you initiate new instance of your model from params, Rails casts your date into Date object (example using my own model):
i = Invoice.new due_date: "29.09.2012"
i.due_date #=> Sat, 29 Sep 2012
i.due_date.class #=> Date
But you can't validate Date with a Regex. What you actually need is
validates :matchdate, presence: true
because it will be nil if Rails can't parse it, and maybe add some custom validators if needed.

Rails how to remove UTC offset text ('UTC') from a dateTime leaving only the DateTime?

I have a tool set to store everything in the db as UTC. On a form I have a text field with an attached jQuery Date + Time picker.
In that textfield the dateTime stamp (w/ UTC offset) will just appear like:
<%= f.text_field :report_time, :size => 22 %>
2012-06-05 15:55:50
However I need this form choice to be in EST. So I need to convert it going to the form and then when the form is submitted. This problem is specific only to when an 'EDIT' action is taken (time already exists in field). If I do any addition or subtraction "UTC" gets stuck on the end in the form text field:
#report.report_time = #report.report_time - 5.hours
=>2012-06-05 10:55:50 UTC
At this point a jQuery DateJS dateparse function I'm using will stop working because it doesn't understand the "UTC" text in the text field holding the dateTime.
How can I take a db UTC time and add/subtract hours without "UTC" getting dropped in the form, or how can you remove the UTC offest information leaving only the raw dateTime information?
How do I:
#report.report_time = #report.created_at - 5.hours
=>2012-06-05 10:55:50 UTC
# do something here to strip " UTC" off the dateTime ??
=>2012-06-05 10:55:50
Thank You!
Rails 2.3.5 / Ruby 1.8.7
Use the strftime function to set the value of the field directly, if you don't want the default representation.
<%= f.text_field :report_time, :size => 22, :value =>"...." %>
http://ruby-doc.org/stdlib-1.8.7/libdoc/date/rdoc/DateTime.html#method-i-strftime
You may probably want to check out this link for information on how to use the date/time more naturally with the form builder.
http://guides.rubyonrails.org/form_helpers.html#using-date-and-time-form-helpers

Rails 3 default datetime format without UTC

I'm creating a new Rails 3 app, and in it I use DateTime for a couple of fields, however every datetime field standard has UTC behind it (in a view), like:
2010-10-10 16:19:00 UTC
How do I get rid of the UTC part?
UPDATE: here's what I have so far:
<%= trip.truckleft.strftime("%Y-%m-%d %H:%M") %>
So all I have to do now is put that in a helper, but isn't there a better more universal way?
I looked at some other posts, that suggested creating a time_formats.rb in initializers, however I didn't have any success doing that.
Thanks for your help, much appreciated!
Another -- perhaps now preferred -- way is to use Rails' internationalization and localization support. There's a lot to learn in that guide, so the tl;dr version is this:
<%= l trip.truckleft, :format => :long %>
There are a few predefined date and time formats like :long available to you already for English, and you can add your own in config/locales/en.yml by following the YAML structure in those examples. If you're not getting heavily into the whole i18n/l10n thing just yet and looking at the l method all the time is confusing, you can also use:
<%= trip.truckleft.to_formatted_s(:long) %>
Here is what finally worked for me:
I created a new file in:
config/initializers/
named: time_formats.rb
and added this to that file:
Time::DATE_FORMATS[:default] = "%Y-%m-%d %H:%M"
Then I saved, restarted the server and it started to work.
I'm using i18n to format my dates and have this in en.yml:
date:
formats:
default: "%m/%d/%Y"
I wanted to reuse that format for how the models show their dates, so my config/initializers/time_formats.rb contains this:
Date::DATE_FORMATS[:default] = lambda { |date| I18n.l(date) }
To be exact, you should put these in your initializers:
Date::DATE_FORMATS[:default] = "%m-%d-%Y"
Time::DATE_FORMATS[:default] = "%m-%d-%Y %H:%M"
When having datetime, the second one will work (for example: created_at for in models).
You can put the following line at the end of your config/environment.rb file:
Date::DATE_FORMATS[:default] = "%Y-%m-%d %H:%M"
for rails 3
add to config/environment.rb
my_datetime_formats = { :default => '%F %T' } #or any other you like
my_date_formats = { :default => '%F' } #or any other you like
Time::DATE_FORMATS.merge!(my_datetime_formats)
Date::DATE_FORMATS.merge!(my_date_formats)
(the difference from other answers - is merge! method)

Rails date format in form field

I'd like my dates in the mm/dd/year format in text fields. However, they currently displays as 2010-03-26.
Is there a global setting I can set to change this?
I tried the following, which seems to update the .to_s method, but form fields stay the same.
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(:default => '%m/%d/%Y')
Thanks
You have to register the default format in an initializer.
Add this line to the config/initializers/date_time_formats.rb.
Date::DATE_FORMATS[:default] = '%m/%d/%Y'
# if you want to change the format of Time display then add the line below
Time::DATE_FORMATS[:default]= '%m/%d/%Y %H:%M:%S'
# if you want to change the DB date format.
Time::DATE_FORMATS[:db]= '%m/%d/%Y %H:%M:%S'
Now in the script\console lets test the format.
>> Date.today.to_s
=> "03/14/2010"
>> Time.now.to_s
=> "03/14/2010 13:20:55"
I don't know if there is a global setting for that anywhere, I just do it in the ERB.
<%= text_field_tag("air_date_date", air_date.blank? ? "" : air_date.strftime("%m/%d/%Y"), :class => "date-input text") %>
Alternatively, you can factor this out into a helper function to make it DRY.
I know this is an awfully old question, but you could use date_field instead of text_field. Perhaps that wasn't an option when you asked this question originally.
It displays the date in mm/dd/yyyy, which is your intent.
<%= date_field :column_name %>
The date_select form helper provides a "bare bones" date selector.

Resources