Intl.DateTimeFormat gives strange result from year 1847 or below

不问归期 提交于 2019-12-11 03:25:20

问题


Why is it that if I choose a year below 1848, the result of this format is May 10?

I have a feeling this could be about time zones? If so how can I avoid this, given that I will be creating a date object from an ISO date string (without time) like this: YYYY-MM-DD.

(Tested on Chrome 59)

const workingDate = Intl.DateTimeFormat('en-GB').format(new Date('Fri May 11  1848 01:00:00 GMT+0100 (BST)'));
const notWorkingDate = Intl.DateTimeFormat('en-GB').format(new Date('Fri May 11  1847 01:00:00 GMT+0100 (BST)'));

console.log(workingDate);
console.log(notWorkingDate);

Date strings above are from e.g. new Date('1847-05-11') (I'm in BST time zone)


回答1:


This test was made in Chrome 53.

I've added some options to DateTimeFormat to check the other fields of the date:

options = {
    year: 'numeric', month: 'numeric', day: 'numeric',
    hour: 'numeric', minute: 'numeric', second: 'numeric',
    hour12: false, timeZoneName: 'long'
};
var workingDate = Intl.DateTimeFormat('en-GB', options).format(new Date('Fri May 11  1848 01:00:00 GMT+0100 (BST)'));
var notWorkingDate = Intl.DateTimeFormat('en-GB', options).format(new Date('Fri May 11  1847 01:00:00 GMT+0100 (BST)'));

The result was:

workingDate: 10/05/1848, 20:53:32 GMT-03:06:28
notWorkingDate: 10/05/1847, 20:53:32 GMT-03:06:28

Most places didn't have standardized UTC-based offsets before 1900 (actually, each country adopted it in a different year), so before 1900 you always get those strange results. Actually, as Matt explained in the comments, UTC was implemented in 1972 and before that most zones were defined as offsets from GMT. Anyway, for very ancient dates, specially before 1900, you might expect offsets like the above.

In this case, it's getting the corresponding offset for my system's default timezone (America/Sao_Paulo): before 1914 it was -03:06:28.

In London (which I'm assuming it's your default timezone), before 1847-12-01 the offset was -00:01:15 (calculated by lat/lon, see again Matt's comment for more details), and after that it was changed to +00:00 (that' why it works for dates in 1848).

I've made a test setting the timezone to Europe/London:

options = {
    year: 'numeric', month: 'numeric', day: 'numeric',
    hour: 'numeric', minute: 'numeric', second: 'numeric',
    hour12: false, timeZoneName: 'long', timeZone: 'Europe/London'
};
var workingDate = Intl.DateTimeFormat('en-GB', options).format(new Date('Fri May 11  1848 01:00:00 GMT+0100 (BST)'));
var notWorkingDate = Intl.DateTimeFormat('en-GB', options).format(new Date('Fri May 11  1847 01:00:00 GMT+0100 (BST)'));

The result was:

11/05/1848, 00:00:00 GMT
10/05/1847, 23:58:45 GMT-00:01:15

Which confirms that before December/1847, dates had a different offset.


One way to fix it, is to consider the date as UTC:

options = {
    timeZone: 'UTC'
};
var workingDate = Intl.DateTimeFormat('en-GB', options).format(new Date('Fri May 11  1848 01:00:00 GMT+0100 (BST)'));
var notWorkingDate = Intl.DateTimeFormat('en-GB', options).format(new Date('Fri May 11  1847 01:00:00 GMT+0100 (BST)'));

The values will be:

11/05/1848
11/05/1847



来源:https://stackoverflow.com/questions/45512717/intl-datetimeformat-gives-strange-result-from-year-1847-or-below

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!