Parsing dates and times in Ruby and Rails
August 11, 2010
Out of the box, Rails’
Let’s start with Chronic for parsing date/time values into something you can store in a database. First, install the gem:
Chronic’s usage is very straightforward. Let’s fire up
script/console to have a look:
> require 'rubygems'
> require 'chronic'
=> Thu Aug 12 12:00:00 -0500 2010
> Chronic::parse('next saturday')
=> Sat Aug 14 12:00:00 -0500 2010
> Chronic::parse('8/12/10 3pm')
=> Thu Aug 12 15:00:00 -0500 2010
So rather than requiring users to use Rails’ default pulldown-based date picker, or enter data in forced formats (like
Say you’re developing a cooking site or project management tool and want to allow users to enter spans of time like “35 minutes,” “1 hour 15 minutes,” “1:30,” or “2 days” and store them in a consistent format. Enter Chronic Duration—it works like Chronic, but for stretches of time as opposed to actual dates or times. After parsing the entry, the duration is stored in the database as the number of seconds. First, install the gem:
$ gem install chronic_duration
Let’s look at it in action using
> require 'chronic_duration'
> ChronicDuration::parse('15 minutes')
> ChronicDuration::parse('1:15') # note this is MM:SS
And so on. Chronic Duration also provides an output method:
> ChronicDuration::output(75, :format => :short)
=> "1m 15s"
> ChronicDuration::output(75, :format => :long)
=> "1 minute 15 seconds"
> ChronicDuration::output(75, :format => :chrono)
Using Chronic and Chronic Duration in Rails
Experimenting with the gems in the console is one thing, but how do we put them to use in a Rails application? Here’s how I do it. Going back to the idea of a project tracker, say I’ve got a model named
Task with a due date and an estimated time field. It might look like this:
class Task < ActiveRecord::Base
attr_accessible :name, :description, :due_at, :estimated_time
self.due_at = Chronic::parse(self.due_at_before_type_cast) if attribute_present?("due_at")
self.estimated_time = ChronicDuration::parse(self.estimated_time_before_type_cast) if attribute_present?("estimated_time")
Don’t forget to include Chronic and Chronic Duration in your
config/environment.rb file, and restart your application.
There are a few ways you could use
ChronicDuration::output in your application’s views—you could either override the accessor in the model by adding something like
ChronicDuration.output(read_attribute(:estimated_time), :format => :long)
or use it in a view helper along the lines of
def display_time(time = 0)
ChronicDuration.output(time, :format => :long)
and use the helper in your views. It depends on what you need to do with the data, so experiment within your application to see what works best.
Chronic doesn’t include a function to return a date value in a pretty format—just use Ruby’s strftime method to handle that.
blog comments powered by
Rails testing made simple
Learn to test Rails apps the way
I learned, building up tests step-by-step, in
Everyday Rails Testing
Expanded to include exclusive content and a complete sample Rails application.
Learn more »