12

In Rails, I see I have a few options to parse a date and a date-time. What is the best practice for parsing dates for the sole purpose of persisting them into the DB via ActiveRecord? And why?

Time.zone.parse(...)
Time.parse(...)
DateTime.parse(...)
Ron Garrity
  • 1,383
  • 2
  • 13
  • 25
  • Also [this](http://stackoverflow.com/questions/9138515/when-should-i-use-datetime-vs-date-time-fields-in-ruby-rails) and [this](http://stackoverflow.com/questions/1261329/whats-the-difference-between-datetime-and-time-in-ruby/1261435#1261435), which says to use DateTime when dealing with Dates or Dates far out in the future. – Ron Garrity May 10 '12 at 15:33

2 Answers2

19

Go with Time.zone.parse if you just want to write into ActiveRecord.

DateTime should be avoided. If you're handling dates, you should use Date.parse instead.

Beyond that, it depends on whether the input comes with timezone information, what the current timezone is set to, and whether you want timezones in your data.

Time.zone.parse will return an ActiveSupport::TimeWithZone, defaulting to UTC.

> Time.zone.parse("12:30")
=> Thu, 10 May 2012 12:30:00 UTC +00:00 

Time.parse will return a Time, with a zone if it's specified in the input, or the local TZ.

> Time.parse("12:30")
=> 2012-05-09 12:30:00 -0700 

For a more detailed explanation of Ruby time comparisons and precision, read this blog post:

http://blog.solanolabs.com/rails-time-comparisons-devil-details-etc/

Adam Lassek
  • 35,156
  • 14
  • 91
  • 107
Jay Moorthi
  • 877
  • 6
  • 8
  • 1
    Time.zone.parse "defaults" to UTC if your Rails app is defaulted to UTC (in environment.rb)... Time.parse defaults to the server local time zone offset regardless of the Rails app. – Pavling May 10 '12 at 07:36
  • Hey, `Time.zone.parse` takes the rails default zone correctly, while DateTime returns UTC. so +1, but is there any other reason for "DateTime should be avoided."? – Karthik T Jun 07 '14 at 14:06
2

Times that are automatically set by ActiveRecord (e.g. created_at and updated_at) come back as ActiveSupport::TimeWithZone instances.

According to the documentation, ActiveSupport::TimeWithZone and Time have the same API, so Time is what I would use.

On an unrelated note, there are methods to_time and to_datetime that you can call on strings:

"2012-05-09".to_time # => 2012-05-09 00:00:00 UTC 
"2012-05-09".to_datetime # => Wed, 09 May 2012 00:00:00 +0000
x1a4
  • 19,417
  • 5
  • 40
  • 40