My time zone solution: RelativeDate.js and ServerTime.js
Posted: October 31st, 2007 Tags: Javascript, My Software, Ruby on Rails, Web development, wshlst.comFor my wshlst.com project, I needed to show when each item or comment was created or edited. My initial implementation was to just show the time and date of the change, but people who aren’t in the same time zone as my server didn’t like the fact that it showed a different time zone.
I contemplated having a per-user time zone setting, but that seemed complicated. So I decided to just show how old the item is. For that, I needed to write two things. I’m posting them here in case anyone else finds them useful.
RelativeDate.js
First, I needed a simple relative date formatter, so I wrote a simple one. Given two dates, it returns a string like
4 days ago
or
26 hours ago
Here’s the code and the JsUnit test:
RelativeDate.js
RelativeDateTest.html
ServerTime.js
The timestamps of the items I’m displaying are stored in the database, so they are based on the clock of my database server. The relative dates are calculated in Javascript, so they are based on the clock of the user, which might be hours or just minutes off from the database server time.
The first thing my app does when it loads is checks to see if the user is logged in, so I decided to piggyback the current server time along with the response. Since the client and server talk using JSON, it’s simple to add another property to the response:
def current
...
render_json({
:success => true,
:user => user,
:servertime => dbtime()
}.to_json)
end
...
def dbtime
ActiveRecord::Base
.connection
.select_all("select unix_timestamp(now()) as now")[0]["now"]
.to_i
end
I wrote a ServerTime class on the client side and I initialize it when the app receives the current user response from the server:
this.serverTime = new ServerTime(json.servertime);
Here’s the code (it’s very simple):
Putting It Together…
And now to display the relative time, my app only has to do this:
var updated = new Date(item.updated_at * 1000); element.insert(new RelativeDate(updated, app.serverTime.get()).toString());