Inconsistent behavior of toLocaleString() in different browser

房东的猫 提交于 2019-11-27 05:25:41
funwhilelost

The short answer is no. toLocaleString can be implemented however the developers wish. What your question implies is that Chrome outputs the string you want.

If you would like to output that format consistently you'll need to use a separate library - like DateJS.

To do this with DateJS will need some standard format specifiers available in core.js and some that are only available in extras.js. The documentation has a list of all the format specifiers.

The string you want is:

Tue Nov 13 2012 10:15:00 GMT+0530 (India Standard Time)

So to get this from DateJS you'll need:

"D M d Y H:i:s \G\M\TO (e)"

The syntax for DateJS is:

new Date ("2012-11-13T04:45:00.00").format("D M d Y H:i:s \G\M\TO (e)");

Instead of using toLocaleString() which is outdated and implemented incorrectly for all web browsers, I strongly suggest using Globalize for date & time formatting.

Then to format date on the client side, all you have to do is to assign valid culture and simply call the format function:

Globalize.culture(theCulture);
Globalize.format( new Date(2012, 1, 20), 'd' ); // short date format
Globalize.format( new Date(2012, 1, 20), 'D' ); // long date format

Pretty simple, isn't it? Well, you'll have to also integrate it with your ASP.Net application, which complicates things a bit. First, you will need to reference the globalize.js the regular way:

<script type="text/javascript" src="path_to/globalize.js"></script>

Then it is best to include the right culture definition, that is the one you will need to use when formatting:

<script type="text/javscript" src="path_to/cultures/globalize.culture.<% = CultureInfo.CurrentCulture.ToString() %>.js"></script>

Finally you will need to set theCulture variable before you use it:

<script type="text/javscript">
    var theCulture = <% = CultureInfo.CurrentCulture.ToString() %>
</script>

Of course the more elegant way to do it, would be to create a property or the method in the code-behind that will write down the appropriate scripts for you and then reference just the method, say:

public string IntegrateGlobalize(string pathToLibrary)
{
  var sb = new StringBuilder();
  sb.Append("<script type=\"text/javascript\" src=\"");
  sb.Append(pathToLibrary);
  sb.AppendLine("/globalize.js\"></script>");
  sb.Append("<script type=\"text/javascript\" src=\"");
  sb.Append(pathToLibrary);
  sb.AppendLine("/cultures/globalize.culture.");
  sb.Append(CultureInfo.CurrentCulture);
  sb.AppendLine(\"></script>");
  sb.Append("<script type=\"text/javascript\">");
  sb.Append("var theCulture = ");
  sb.Append(CultureInfo.CurrentCulture);
  sb.AppendLine(";</script>");

  return sb.ToString();
}

Then all you have to do, is to reference this method in the (master?) page head:

<head>
  <% = IntegrateGlobalize("path_to_globalize") %>
  ...
</head>

Some issues

If you want to do it 100% correctly, you will need to enhance the Globalize culture generator to include 'g' format switch and then use this exact switch on the client side to format date:

Globalize.format( new Date(2012, 1, 20), 'g' ); // default date format

Why is that? Because 'g' is a default date format. This is what you'll get when you simply call DateTime's ToString() method without parameters (which will imply CultureInfo.CurrentCulture as the only parameter...). The default format is best, it will be either short or long, or any other, but the most commonly used by people using this culture.

I said that toLocaleString() is wrong for all web browsers. Why is that? That's because it will use web browsers settings and not the server-side detected culture. That means, that you might have mixed cultures in the same web page. That may happen if some of your dates are formatted on the server side and some other on the client side. That's why we needed to pass (detected) culture from the server side.
BTW. If you decide to include the regional preferences dialog to your web application, the mismatch would be even more visible, as toLocaleString() won't follow user settings...

To convert a time to a locale-specific string on the server, you can use the method DateTime.ToLongDateString. On that page, see the note about the "current culture object" (on the server) of class DateTimeFormatInfo. Make sure that's set correctly.

The root cause of this issue was never addressed by any of the answers. The OP said:

I am receiving Data Time from server something like this 2012-11-13T04:45:00.00 in GMT format.

GMT is not a format. This string is in ISO 8601 extended format, without any time zone specified. The ISO 8601 spec says that without a qualifier, this is intended to represent local time. To specify GMT, you would append a Z to the end, or you could append an offset such as +00:00.

The problem is, ECMAScript (v1 - v5.1) did not honor this provision in the spec. It actually said that should be interpreted as UTC instead of local time. Some browsers honored the ISO spec, some honored the ECMA spec. This has been corrected for version 6, and most browsers have complied.

So - if you intend to transmit UTC/GMT based timestamps, then on the server side, you should always send a Z so there is no ambiguity.

Still, even if the value is correctly interpreted, there's no guarantee that the strings will be formatted the same across browsers. For that, you do indeed need a library. I recommend moment.js, but there are others.

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