jsalonen
jsalonen

Reputation: 30501

How to use Date objects in local timezone with Backbone.js sync?

I am using Backbone.js sync to store my models to a database.

The problem is that Backbone.js sync converts Date from my local timezone format into a UTC Date. I have traced this back to use of JSON.stringify within Backbone.js sync:

params.data = JSON.stringify(model.toJSON());

As an example what happens here:

>>> var a = {myDate: new Date();}
>>> JSON.stringify(a);
>>> a
"{"myDate":"2012-05-04T21:58:34.734Z"}"

As such, when I use Backbone.js sync again to retrieve the same resource, my timezone is converted to UTC. I would wish instead to have the original, local timezone preserved.

For me it is OK that the data is stored to the database as UTC, just as long as I somehow manage to convert it back to the local timezone.

All help is approciated.

Upvotes: 1

Views: 3757

Answers (1)

mu is too short
mu is too short

Reputation: 434765

All communication with the server should be done in UTC so JSON.stringify is doing what you want it to. Your missing piece seems to be converting the UTC timestamp that you get from the server into the browser's local time zone.

You can intercept the server's JSON before it goes into your model by providing a parse implementation in your model:

parse model.parse(response)

parse is called whenever a model's data is returned by the server, in fetch, and save. The function is passed the raw response object, and should return the attributes hash to be set on the model. The default implementation is a no-op, simply passing through the JSON response. Override this if you need to work with a preexisting API, or better namespace your responses.

That will get you an object {myDate: '2012-05-04T21:58:34.734Z'} in response so you just have to convert that to your local timezone. A quick combination of Date.parse and new Date will give you a Date object in the browser's timezone:

var d = new Date(Date.parse(response.myDate));
// Fri May 04 2012 14:58:34 GMT-0700 (PDT)

If you want Date objects in your model then you just need to return the Date wrapped in an object:

return { myDate: d };

or, if response has more things you could:

response.myDate = d;
return response;
// or if you don't want to modify response
return _({}).extend(response, { myDate: d });

If you for some reason you wanted an ISO-8601 string in the browser's timezone then you could easily build one using the standard Date methods; I think you'd be better off keeping the Date object though, that's far more useful than the string.

Upvotes: 10

Related Questions