2

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)

Dominic
  • 62,658
  • 20
  • 139
  • 163
  • See [*Why does Date.parse give incorrect results?*](https://stackoverflow.com/questions/2587345/why-does-date-parse-give-incorrect-results) – RobG Aug 05 '17 at 01:43

1 Answers1

3

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

  • 1
    GREAT answer! Thanks. I won't ask why you're on Chrome 53 ;) – Dominic Aug 04 '17 at 18:33
  • You're welcome, glad to help! Well, I'm also surprised that Chrome isn't updated... –  Aug 04 '17 at 18:36
  • 2
    Great answer, but just to correct a few points: 1) UTC wasn't implemented until 1972. Before then, most (but not all) time zones were defined as offsets from GMT. 2) The `-00:01:15` offset describes the [local mean time](https://en.wikipedia.org/wiki/Local_mean_time), not a standard time. In other words, there was no point in the past where the government said they were 1¼ minutes behind GMT or UTC. Instead it's calculated by lat/lon. Note that one can see this by [the tzdb entry](https://github.com/eggert/tz/blob/2017b/europe#L464) being labeled as LMT. Cheers! – Matt Johnson-Pint Aug 04 '17 at 21:44
  • @MattJohnson Thanks for the info, I wasn't sure about when UTC was implemented (and should've searched before posting). I've updated the answer, thanks a lot! –  Aug 04 '17 at 21:53
  • The argument regarding offsets is not necessarily correct. Until recently, ECMAScript was supposed to apply the current offset as if it had always existed, so there was no history of offset changes for a particular host (other than daylight saving for the current settings). Also, the [*timezone offset is always UTC*](http://ecma-international.org/ecma-262/8.0/#sec-local-time-zone-adjustment), regardless of when it was introduced. There is no allowance for history. – RobG Aug 05 '17 at 01:46
  • 1
    @MattJohnson—LMT is calculated from longitude only. ;-) – RobG Aug 05 '17 at 01:50