Recently i have been writing a simple web-based reminder app which requires one to input dates and times. To input the date and time, normally one would add some sort of calendar widget which pops up.

But personally i think this tends to be really awkward, especially if you don’t want to be specific about dates or times. e.g. Speculative Opportunities. It also requires a lot of mouse clicking to find and enter the correct date and time.

Fortunately, there are libraries about which aim to solve this issue by allowing you to specify the time in English. Typically they are referred to as “Natural language” date/time parsers. In my case, i found one called Chronic which is distributed as a gem for Ruby. It has even got a nice screencast.
sudo gem install chronic
Consisting of only one public function, Chronic is really easy to use:
require 'chronic'
Chronic.parse("tomorrow at 5")
#=> Fri Aug 08 17:00:00 +0100 2008
See? Nice and simple. We can also use the options to help chronic get the right time. e.g. If i really meant to say “Tomorrow at 5 AM”, i could fix it like this:
require 'chronic'
Chronic.parse("tomorrow at 5", :ambiguous_time_range => :none)
#=> Fri Aug 08 5:00:00 +0100 2008
The options you can choose from are as follows:
- :context - the context in which the time is assessed (:past or :future).
- :now - current time.
- :guess - if false, this returns a time range instead of guessing at a specific time.
- :ambiguous_time_range - range in hours in which an ambiguous time will be resolved. Best to think of it as hours to skip in the day when picking a time. e.g. setting this to 18 and inputting 5 will result in 5am the next day being chosen.
Sadly i couldn’t seem to find any way of setting which time zone to evaluate the time in. This would have been useful when working with Ruby on Rails 2.1’s new TimeZone support. Fortunately though, i figured out a workaround which is as follows:
# grab time using current time zone as reference
ctime = Chronic.parse(value, :now => Time.zone.now)
# re-interpret time in current timezone
ctime = Time.zone.local(ctime.year, ctime.mon, ctime.day, ctime.hour, ctime.min, ctime.sec)
Basically this gives Chronic the time in the current time zone, which deals with relative times (e.g. “tomorrow”). It also re-interprets the calculated time in case you are a bit more specific (e.g. “5AM”).
For something a bit less hackish, one might want to check out technoweenie’s fork on github. This appears to allow you to tell Chronic to use a different Time class for calculating times, which should solve the problem.
So to conclude, i think Chronic is a nice and simple solution that works rather nicely for common cases.
Other libraries
If you aren’t using Ruby, have no fear. There are similar “Natural language” parsers available for other programming environments which work in a similar fashion to Chronic.
- Datejs for JavaScript
- parsedatetime for Python
- DateTime::Format::Natural for Perl
- DateTimeEnglishParser for .net

Add New Comment
Thanks. Your comment is awaiting approval by a moderator.
Do you already have an account? Log in and claim this comment.
Add New Comment
Trackbacks
(Trackback URL)