getFullYear returns year before on first day of ye

2019-02-24 06:56发布

问题:

I'm trying to pull just the year out of a date, but for some reason on the first day of the year its returning the year previous.

new Date('2012-01-01').getFullYear()

will return '2011' and

new Date('2012-01-02').getFullYear()

will return '2012'

Any good ideas on what I'm doing wrong? or a fix for this would be helpful.

回答1:

new Date('2012-01-01') will parse the date assuming it's in UTC. The created Date object incorporates your timezone, so it will take that into account when printing out the result of getYear(). If you're in GMT-anything, that means you're going back to the previous year. You can ignore timezones and deal with just UTC by calling Date.prototype.getUTCFullYear().



回答2:

new Date(dateString) will return what time it was in Greewich England at that time. You could do this if you want the year you seek:

new Date('2012-01-01T00:00:00').getFullYear();

Maybe you like this:

function dateFromString(dateString){
  return new Date(dateString+'T00:00:00');
}
console.log(dateFromString('2012-01-01').getFullYear());


回答3:

As others have said, your issue is that the host is parsing '2012-01-01' as if you are in GMT and the time is 00:00:00. However, your system is set for a timezone that is west of Greenwich, and that is taken into account when getting the year of the date so you get a date for 31 December in the previous year.

A fundamental rule is to never parse strings using the Date constructor (or Date.parse, which does the same thing) as it is largely implementation dependent and inconsistent. An ISO 8601 date without a timezone should be treated as local according to ISO. However, in ECMAScript ed 3 it could be treated as anything (IE up to and including version 8 didn't parse it at all). Then ES5 said to treat it as UTC (in conflict with ISO). Then ECMAScript 2015 seemed to infer treating it as local, which browsers started to do, but then TC39 said treat it as UTC, which is what most modern browsers do (but there are still plenty of older browsers around that don't).

So if you want consistency, parse date strings manually, e.g. to treat an ISO 8601 date as local, use a function like:

/*  Parse ISO 8601 date string without time zone
**  as a local date
**  @param {string} s - date string to parse in format yyyy-mm-dd
**  @returns {Date}   - local Date, or invalid date if any value is
**                      out of range
*/
function parseISOLocal(s) {
  var b = s.split(/\D/);
  var d = new Date(b[0], --b[1], b[2]);
  return d && d.getMonth() == b[1]? d : new Date(NaN);
}

var s = '2012-01-01';

document.write(parseISOLocal(s))