Reputation: 26434
I was playing around with the Date
object in JavaScript and found a very strange behavior.
If you create a new date with 1 parameter and call the getFullYear
method, it will return 1 less than what you passed in
new Date("2014").getFullYear()
=> 2013
To test a theory, that it would return "2014-1-1", and in the previous timezone, the year before, I did another test.
new Date("2014").getDate()
=> 31
new Date("2014").getMonth()
=> 11
This would support the timezone theory, but it still doesn't explain the next two examples.
If you type in an alphanumeric string, you will get the correct year. It even works for gibberish like this
new Date("hsdkjfuweirsdf 2014").getFullYear();
=> 2014
For the first example, I assumed the function started counting at 0, so the year would be 1 less. However, that doesn't explain why my second function returned the correct year.
Edit:
I found another strange behavior with the new Date()
constructor. If you pass in multiple parameters, it will return the correct year as well
new Date("2014", "9").getFullYear()
=> 2014
All of the above tests were done multiple times in Google Chrome.
Upvotes: 0
Views: 200
Reputation: 123423
In the first case, the date string is being detected as partially following the one official Date Time String Format:
ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 Extended Format. The format is as follows:
YYYY-MM-DDTHH:mm:ss.sssZ
And, at least with the 5th edition of ECMAScript, that your browser is currently adhering to:
The value of an absent time zone offset is “Z”.
With this, the date string is assumed to be in UTC/GMT time for parsing.
Date.parse("2014") === Date.parse("2014-01-01T00:00:00Z");
Then, getFullYear()
provides the year for the same "moment" in your local time zone, compared to its equivalent UTC
method.
new Date("2014").getFullYear() // 2013 (or 2014 for users in UTC+N timezones)
new Date("2014").getHours() // (not 0, unless you live in UTC+0)
new Date("2014").getUTCFullYear() // 2014
new Date("2014").getUTCHours() // 0
The 2nd example, by including the gibberish before the year, fails to match the above format, even partially.
Since that's the only format officially defined in the specification, the browser is now on its own to determine if and how it should parse the date string.
If the String does not conform to [the Date Time String Format] the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
And, it chooses to use your local time zone by default and largely ignore the gibberish.
new Date("hsdkjfuweirsdf 2014").getFullYear() // 2014
new Date("hsdkjfuweirsdf 2014").getHours() // 0
Note: The most recent, 6th edition of ECMAScript has changed the assumed value for date strings lacking timezones:
If the time zone offset is absent, the date-time is interpreted as a local time.
Upvotes: 2
Reputation: 39017
This is definitely an effect of Date
parsing for UTC vs local time zone.
Generally, if you give any string that can be "fit" to ISO 8601 format the Date()
constructor will try to parse you a GMT-located object. Otherwise it will give you your own local (with your browser's timezone info) object.
// how many minutes to add to get GMT?
var tzOffset = new Date().getTimezoneOffset()
// 300 // Eastern Standard Time, GMT-5
// will be parsed as GMT:
var gmt = new Date("2011");
// what year is it for me?
gmt.getFullYear()
// 2010
This is the local year when GMT experiences January 1, 2011. (It's still 2010 in NYC when London celebrates the New Year)
Notably, there are UTC functions:
// what year is it in London?
gmt.getUTCFullYear()
// 2011
Let's see what happens when we "add" hours so that our local time catches up:
// add tzOffset, voila, "correct" year
var localyear = new Date(gmt.getTime() + tzOffset*60*1000).getFullYear()
// 2011
Also, Chrome does a "best effort" to parse junk (non-standard) strings. This is browser-dependent behavior, and rely on it at your own risk. This explains the local-time-located behavior for strings such as "hsdkjfuweirsdf 2014"
.
Upvotes: 1