According to the documentation, when a string is passed to the constructor of Date
, it accepts the same formats accepted by Date.parse
. This method, in turn, follows some rules.
When the string has only the date (year, month and day) in the format "YYYY-MM-DD" (which is the format defined by ISO 8601 standard), to documentation says this is interpreted as UTC (moreover, the time is considered to be midnight).
The problem is that the methods getters (as getMonth()
, getDate()
, etc), return the values according to the browser’s Timezone (which usually follows the time zone configured in the operating system).
In my case, for example, my browser is configured with the Brasilia Time. When creating new Date('1988-03-01')
, I’m actually saying that the date is "March 1, 1988 at midnight in UTC". And March 1, 1988 at midnight in UTC corresponds to February 29 at 9:00 in Brasilia Time.
When using the getters, the values returned correspond to the Timezone of the browser (that will not always be equal to UTC), so gives this "1 day difference". Ex:
let data = new Date('1988-03-01');
// meu browser está no Horário de Brasília, o resultado pode variar de acordo com a config do seu
console.log(`${data.getFullYear()}-${(data.getMonth()+1)}-${data.getDate()}`); // 1988-2-29
Fortunately, there are methods to obtain the values according to UTC (such as getUTCMonth
, getUTCDate
, etc.):
let data = new Date('1988-03-01');
console.log(`${data.getUTCFullYear()}-${(data.getUTCMonth()+1).toString().padStart(2, '0')}-${data.getUTCDate().toString().padStart(2, '0')}`); // 1988-03-01
I also used padStart
to set zero to the left of the month and day (so is written 03
instead of 3
).
As to the your comment, that "works" when the string is 1988-03-1
, actually it depends on the browser.
According to this part of the Ecmascript specification: "if the string does not conform to this format, any heuristic or implementation-specific format can be used."
In this case, "this format" refers to ISO 8601, which defines that the day and month are always written with 2 digits. So when the string is 1988-03-1
(the day with only 1 digit), the format is no longer ISO 8601, and therefore each browser can interpret in a different way. Chrome ends up considering that the date is in the browser Timezone, and the getters end up returning the correct result. But in Firefox, it keeps considering UTC, and the error occurs the same way (see a more detailed discussion about these differences here).
someone can explain why when I change the string
dataSTR = '1988-03-01'
fordataSTR = '1988-03-1'
the "[Format Desired]" works correctly?– Gustavo Novais