Handling time nicely with moment.js

As every developer knows, handling timezones and the like is a real PITA. The best minds of our generation have dashed themselves against the jagged rocks of Daylight Savings Time and that part of Indiana that’s always 30 minutes behind the rest of Indiana.

While that detail isn’t necessarily solved by moment.js, lots of other gnarly issues are. This library by Tim R. Wood makes working with dates in Javascript a real pleasure. I’ll take just a moment to show you some of the hurdles we overcame with it.

In our application, like all good developers are storing all dates in UTC. Specifically, we are passing date strings in JSON to a PHP backend that will treat them as UTC. Given that, the backend requires a specific format which is a variation of the typical JSON date time ISO format you’ve probably seen. All dates should be in the form: 2012-10-22 15:36:32.

We want to let our users provide us dates in whatever timezone their current browser uses. In our case, we’re using a jQuery time picker plugin by Trent Richardson. When our users are picking dates, we’re telling the time picker to format them like this: Oct 22, 2012 3:36 pm.

Clearly, we’ll need to translate these times as we move back and forth from the data layer to the presentation layer. To translate the UTC string to user-local time, we simply do this (where post_at is the string representation of UTC time from the data layer):

moment.utc( post_at, "YYYY-MM-DD HH:mm:ss" ).local().format( "MMM DD, YYYY h:mm a" );

So, what we’re doing more specifically is creating a moment object in utc() mode. We are passing in the datetime string to parse into a Date() object and the format string of that datetime. We then translate the object to user-local time with local() and then format into format we like for our time picker plugin.

Going the other way around, we do the reverse essentially. This time, post_at is the value from the time picker’s input text field:

moment( post_at, "MMM DD, YYYY h:mm a" ).utc().format( "YYYY-MM-DD HH:mm:ss" );

We first create a moment object in local mode passing it our value and a format string. Switch modes to utc() and then format for the data layer.

I originally had about 20 lines of gnarly Date() object manipulations to do the work of this two lines of code. Plus, I think my original code was wrong.

moment.js does lots of other nice things as well. Such as the simple:


to the sublime:

moment.duration(24, "hours").humanize();  // a day

There’s lots of other great features like relative time output:

moment([2007, 0, 29]).fromNow();     // 4 years ago

And for those of you coming from Python who love timedelta objects:

var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
a.diff(b) // 86400000

This library has made a difficult problem easy for us to solve. We’ve been able to do the right thing for our users and for our database’s sanity. I highly recommend everyone writing javascript applications to give it a look.

Comments !