35

I've run into a super strange thing that apparently is IE-specific in toLocaleString on dates.

In the IE console window:

new Date("2014-08-28T20:51:09.9190106Z").toLocaleString();
"‎8‎/‎28‎/‎2014‎ ‎1‎:‎51‎:‎09‎ ‎PM"

Now, type out that string manually as a string and compare it to what the method returned:

"8/28/2014 1:51:09 PM" === new Date("2014-08-28T20:51:09.9190106Z").toLocaleString();
false

Does anyone have any idea why this is occurring in IE? This doesn't occur in Chrome.

Update: more examples:

new Date("8/28/2014 1:51:09 PM")
[date] Thu Aug 28 2014 13:51:09 GMT-0700 (Pacific Daylight Time)[date] Thu Aug 28 2014 13:51:09 GMT-0700 (Pacific Daylight Time)

new Date(new Date("2014-08-28T20:51:09.9190106Z").toLocaleString())
[date] Invalid Date[date] Invalid Date
John Gardner
  • 24,225
  • 5
  • 58
  • 76

5 Answers5

25

First, a bit of background: IE11 implemented the ECMA-402 ECMAScript Internationalization API that redefined Date.prototype.toLocaleString (as well as toLocaleDateString and toLocaleTimeString) as calls to format on Intl.DateTimeFormat. As such, d.toLocaleString() is equivalent to

Intl.DateTimeFormat(undefined, {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric'
}).format(d)

You might think that this is pretty explicit but browsers are allowed a large amount of leeway with what formats they support and what characters compose the format. This is by design - with all the locales and languages around the planet, specifying this would be quite burdensome and very difficult to keep up-to-date. For this reason you cannot expect to be able to compare the results of toLocaleString across browsers or even expect the same browser to continue giving the same result from release to release. As the underlying locale data changes (perhaps because local custom has changed, or more data is available, or better formats are added), so too will the format that is returned from this API.

The takeaway from this is that you should try not to rely on comparing the output of the toLocaleString APIs with some static value in your application. Further, given a date d, Date.parse(d.toLocaleString()) may work sometimes but not others depending on locale, so it's best to avoid this as well.

With that said, en-US is relatively stable and for the most part browsers do (for now) agree on what that basic format is. However, IE inserts bidirectional control characters around the date. This is by design so the output text will flow properly when concatenated with other text. This is especially important when mixing LTR and RTL content such as concatenating a formatted RTL date with LTR text.

Brian Terlson
  • 9,330
  • 1
  • 21
  • 18
  • which is what we ended up doing, first changing our tests to not depend on the specific output of `toLocaleString` , and then later to only use the `toLocaleString` in our knockout template binding instead of in the code itself, and to leave the date objects as actual dates in the rest of the code. – John Gardner Sep 12 '14 at 17:10
15

Use

Str.replace(/[^ -~]/g,'')

This will remove unwanted special characters.

Pang
  • 9,564
  • 146
  • 81
  • 122
Sudip Barman
  • 159
  • 1
  • 3
7

It turns out you can't see them, but IE's Date.toLocaleString is apparently including left-to-right marks in it (U+200E):

8<200E>/<200E>21<200E>/2014<200E> <200E> 9<200E>:<200E>16<200E>:<200E>:18<200E> <200E>AM

awesome. I guess it is time to submit a bug to IE?

John Gardner
  • 24,225
  • 5
  • 58
  • 76
1

Please look at http://jsbin.com/mehowehase/1/edit?html,js,console

var dt = new Date();
var x = dt.toLocaleDateString();
console.log("length : "+x.length);
var arr = x.split("/");
console.log("month : "+parseInt(arr[0],10));

In the above the length of x is 14 in IE but 9 in other browsers. This supports John's comment that IE is adding left-to-right marks. This definitely looks like a bug to me.

dev
  • 19
  • 1
  • 1
    we think it is a bug, the IE/Edge team was the one to actually respond above, and "You might think that this is pretty explicit but browsers are allowed a large amount of leeway with what formats they support and what characters compose the format. This is by design - with all the locales and languages around the planet, specifying this would be quite burdensome and very difficult to keep up-to-date." – John Gardner Nov 04 '15 at 20:30
0

I don't see this in my IE11 so it could be something to do with your settings/config in IE or your machine. For me the result is:

"‎28‎/‎08‎/‎2014‎ ‎21‎:‎51‎:‎09" === new Date("2014-08-28T20:51:09.9190106Z").toLocaleString(); true

Did you copy-paste the date string passed to the constructor from a web page?

I don't think the IE team will accept it as a bug at this stage because it doesn't have clear repro steps

danwellman
  • 9,068
  • 8
  • 60
  • 88
  • given where I work, they might accept it :) We can repro this in unit tests in QUnit using IE, etc, everyone in our org can. – John Gardner Sep 03 '14 at 19:46