1

I am trying to use the fullcalendar.io jquery plugin in my web application. For that, I parse a set of event data into fullcallendar's format like this:

Date.prototype.addHours = function(h) {
        this.setHours(this.getHours() + h);
        return this;
    }

    Date.prototype.addMins = function(h) {
        this.setMinutes(this.getMinutes() + h);
        return this;
    }


data.forEach(function(entry) {
            events[i] = {
                title : 'Clase',
                start : new Date(entry.date),
                end : new Date(entry.date).addHours(entry.hours).addMins(entry.mins)
            }
            i++;
        });

Now my data is formated like this:

[{"date":"2015-05-01T15:00:00.000","hours":4,"mins":30},{"date":"2015-05-04T15:00:00.000","hours":4,"mins":30}, ... ]

However when I create a Date object for 15:00 hours, I get a 17:00 time. I am sure this is related to timezone (I am currently in GMT+2 due to summer time), but I'm not sure how to fix it.

2
  • When working with dates, use something like moment.js
    – Jamiec
    Commented Apr 17, 2015 at 8:43
  • Seems that you answer your question.
    – romuleald
    Commented Apr 17, 2015 at 8:46

3 Answers 3

4

Sadly, when ES5 added the date/time format to JavaScript, they made a mistake: They said that strings without a timezone should be treated as though they were GMT, not local time; but in ISO-8601, which is what they based the format on, strings without timezones are local time.

ES6 changes it to match ISO-8601, so now we have a problem: Some engines use the ES5 rule (current Firefox, for instance), and some engines use the ES6 rule (current Chrome, for instance).

So you need to specify a timezone on those strings to parse them reliably, cross-browser:

  • If they're meant to be GMT, it's easy: Just add a Z to them:

    var dt = new Date(entry.date + "Z");
    
  • If they're meant to be local time, it's harder, because you have to allow for DST, so the offset to use varies by the date.

    var dt = new Date(entry.date + "Z");
    dt.setMinutes(dt.getMinutes() + dt.getTimezoneOffset());
    

    I think that still works correctly on DST boundaries, but you'll want to test.

You can handle this yourself, or you can use a library to handle it for you. There are several choices, just search for "JavaScript date library". One quite popular one at the moment (no pun) is http://momentjs.com.

Example of #1, just adding Z to make those times GMT/UTC reliably:

Date.prototype.addHours = function(h) {
  this.setHours(this.getHours() + h);
  return this;
};

Date.prototype.addMins = function(h) {
  this.setMinutes(this.getMinutes() + h);
  return this;
};

var data = [{
  "date": "2015-05-01T15:00:00.000",
  "hours": 4,
  "mins": 30
}, {
  "date": "2015-05-04T15:00:00.000",
  "hours": 4,
  "mins": 30
}];

data.forEach(function(entry) {
  snippet.log(entry.date + " => " + new Date(entry.date + "Z"));
});
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Example of #2, assuming the strings are local time:

Date.prototype.addHours = function(h) {
  this.setHours(this.getHours() + h);
  return this;
};

Date.prototype.addMins = function(h) {
  this.setMinutes(this.getMinutes() + h);
  return this;
};

var data = [{
  "date": "2015-05-01T15:00:00.000",
  "hours": 4,
  "mins": 30
}, {
  "date": "2015-05-04T15:00:00.000",
  "hours": 4,
  "mins": 30
}];

data.forEach(function(entry) {
  var dt = new Date(entry.date + "Z");
  dt.setMinutes(dt.getMinutes() + dt.getTimezoneOffset());
  snippet.log(entry.date + " => " + dt);
});
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

2

When working with dates in JavaScript it usually a good idea to use something like Moment.js.

Using Moment.js this is trivially easy...

moment('2015-05-01T15:00:00.000').toDate();
0

Use number of milliseconds since January 1, 1970, 00:00:00 UTC whenever working with dates.

Get the milliseconds from a date:

new Date().getTime()

Convert to date (this will always resolve to the same moment in time, regardless of client's timezone):

new Date(1429260375956)

Not the answer you're looking for? Browse other questions tagged or ask your own question.