14

I need a js Date object with specified values for date and year. I would expect new Date("2000-01-01") to give me Date object with 2000 as value for getFullYear(), but if my computer's time settings are set to Chicago timezone, I'm getting Fri Dec 31 1999 18:00:00 GMT-0600 (CST), and for Buenos Aires: Fri Dec 31 1999 22:00:00 GMT-0200 (ARST).

Is there a way to create Date object, with .getFullYear() returning the date we set in constructor, no matter what timezone is set on user's machine?

Update: I need this Date object to be used in another library (which calls its .getFullYear() method, so using UTC getters doesn't really help.

eagor
  • 9,150
  • 8
  • 47
  • 50
  • REF for getfullyear_method http://www.thesstech.com/javascript/date_getfullyear_method – Sohail Arif May 24 '16 at 13:56

3 Answers3

32

When parsing a string to a Date in JavaScript, a value that is in YYYY-MM-DD format is interpreted as a UTC value, rather than a local-time value.

The key is that the parts are separated by hyphens, and that there is no time zone information in the string. The ECMAScript 5.1 Spec says in §15.9.1.15:

... The value of an absent time zone offset is “Z”.

That means, if you don't specify an offset, it will assume you meant UTC.

Note that since this is the opposite of what ISO-8601 says, this is behavior has been changed in ECMAScript 2015 (6.0), which says in §20.3.1.16:

... If the time zone offset is absent, the date-time is interpreted as a local time.

Therefore, when this provision of ES6 is implemented properly, string values of this format that used to be interpreted as UTC will be interpreted as local time instead. I've blogged about this here.

The workaround is simple. Replace the hyphens with slashes:

var s = "2000-01-01";
var dt = new Date(s.replace(/-/g, '/'));

Another workaround that is acceptable is to assign a time of noon instead of midnight to the date. This will be parsed as local time, and is far enough away to avoid any DST conflicts.

var s = "2000-01-01";
var dt = new Date(s + "T12:00:00");

Alternatively, consider a library like moment.js which is much more sensible.

var s = "2000-01-01";
var dt = moment(s, 'YYYY-MM-DD').toDate();
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Thank you! saved my day! but where does the trick with slashes come from? – eagor Mar 23 '15 at 11:08
  • 2
    Using slashes makes it a non-ISO compliant string, which most implementations will interpret as a local time. Keeping it in `yyyy/mm/dd` format instead of `mm/dd/yyyy` or `dd/mm/yyyy` also helps to eliminate regional issues. – Matt Johnson-Pint Mar 23 '15 at 18:09
  • 1
    what if I also have time, like: `"2015-06-01T11:31:01"`. Any way to do it without using moment.js? Thanx – eagor Aug 27 '15 at 08:32
  • @eagor - replace the `T` with a space and it should work. – Matt Johnson-Pint Aug 28 '15 at 20:32
  • This is still a little ambiguous to me. Perhaps: "*Date-only forms are treated as UTC. Date+time (no timezone) are treated as local, and Date+time+timezone are treated as if they are in the timezone*" or something like that. – RobG May 19 '17 at 23:01
3

You can write new method to 'Date.prototype', and use it to get date which will be including the local timezone offset.

  //return the date with depend of Local Time Zone
  Date.prototype.getUTCLocalDate = function () {
    var target = new Date(this.valueOf());
    var offset = target.getTimezoneOffset();
    var Y = target.getUTCFullYear();
    var M = target.getUTCMonth();
    var D = target.getUTCDate();
    var h = target.getUTCHours();
    var m = target.getUTCMinutes();
    var s = target.getUTCSeconds();

    return new Date(Date.UTC(Y, M, D, h, m + offset, s));
  };
yavor.makc
  • 87
  • 1
  • 2
0

Here is a little trick that may help someone:

let date = new Date();
console.log(date); // -> Fri May 28 2021 01:04:26 GMT+0200 (Central European Summer Time)

const tzOffsetMin = Math.abs(date.getTimezoneOffset()) // the minutes of the offset timezone
const tzOffsetHour = tzOffsetMin / 60; // timezone offset in hour
console.log(tzOffsetHour); // -> 2

date.setHours(date.getHours() + tzOffsetHour); // sum to date hour the timezoneoffset
const isovalue = date.toISOString();
console.log(isovalue); // -> 2021-05-28T01:04:26.156Z

In this way you "bypass" the timezone offset wherever you are

Simone Colnaghi
  • 682
  • 8
  • 11