toLocaleString() 在不同浏览器中的不一致行为

IT技术 javascript jquery datetime multiple-browsers
2021-03-11 07:13:58

我正在做一个项目,我必须处理很多日期和时间。服务器端技术是 ASP.Net,在客户端我使用 jQuery 和 jQuery Week Calendar(一个 jQuery 插件)。

所以这里是描述的问题,我正在从服务器接收数据时间,2012-11-13T04:45:00.00格式为 GMT 格式。

现在在客户端,我希望将此日期时间转换为区域设置日期时间格式,例如 IST、EST、PKT 等。

为了实现这一点,我使用了 JavaScript 方法toLocaleString()这仅在 Chrome 中工作正常,在其他浏览器中工作不一致。

以下是它在不同浏览器中的输出:

谷歌浏览器(工作正常):

称呼:

new Date ("2012-11-13T04:45:00.00").toLocaleString();

输出:

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

火狐浏览器:

称呼:

new Date ("2012-11-13T04:45:00.00").toLocaleString();

输出:

Tuesday, November 13, 2012 4:45:00 AM

苹果浏览器:

称呼:

new Date ("2012-11-13T04:45:00.00").toLocaleString();

输出:

Invalid Date

IE浏览器:

称呼:

new Date ("2012-11-13T04:45:00.00").toLocaleString();

输出:

Tuesday, November 13, 2012 4:45:00 AM

目前这些是我测试的浏览器。

这是问题

2012-11-13T04:45:00.00无论使用哪种浏览器客户端,我都需要一种将数据时间(具有这样的格式)转换为区域设置日期和时间的方法。

4个回答

最简洁的答案是不。toLocaleString 可以按照开发人员的意愿实现。您的问题意味着 Chrome 会输出您想要的字符串

如果您想一致地输出该格式,您将需要使用一个单独的库 - 如DateJS

要使用 DateJS 做到这一点,需要一些 core.js 中可用的标准格式说明符和一些仅在 extras.js 中可用的标准格式说明符。该文档包含所有格式说明符的列表

你想要的字符串是:

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

因此,要从 DateJS 获取此信息,您需要:

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

DateJS 的语法是:

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

我强烈建议您使用Globalize进行日期和时间格式化而不是使用toLocaleString()which 已过时且对所有 Web 浏览器实施不正确

然后在客户端格式化日期,您所要做的就是分配有效的文化并简单地调用格式函数:

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

很简单,不是吗?好吧,您还必须将它与您的 ASP.Net 应用程序集成,这会使事情变得有点复杂。首先,您需要以常规方式引用 globalize.js:

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

那么最好包含正确的文化定义,这是您在格式化时需要使用的定义:

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

最后,您需要theCulture在使用之前设置变量:

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

当然,更优雅的方法是在代码隐藏中创建一个属性或方法,为您写下适当的脚本,然后仅引用该方法,例如:

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();
}

然后你所要做的就是在(主?)页头中引用这个方法:

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

一些问题

如果您想 100% 正确执行此操作,则需要增强全球化文化生成器以包含'g'格式开关,然后在客户端使用此确切开关来格式化日期:

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

这是为什么?因为 'g' 是默认日期格式。这就是您在不带参数DateTimeToString()情况下简单地调用方法(这意味着CultureInfo.CurrentCulture它是唯一的参数...)时会得到的结果。默认格式是最好的,可以是短格式或长格式,也可以是任何其他格式,但这是使用这种文化的人们最常用的格式。

我说这toLocaleString()对所有网络浏览器都是错误的。这是为什么?那是因为它将使用 Web 浏览器设置而不是服务器端检测到的文化。这意味着,您可能在同一个网页中具有混合文化。如果您的某些日期在服务器端格式化而另一些在客户端格式化,则可能会发生这种情况。这就是为什么我们需要从服务器端传递(检测到的)文化。
顺便提一句。如果您决定将区域首选项对话框包含到您的 Web 应用程序中,toLocaleString()则不匹配将更加明显,因为不会遵循用户设置...

嘿,如果您查看 Globalize 插件的内部,您会注意到它在内部使用 toLocaleString。当我的所有整数开始在 IE 上出现两个十进制零时,我已经偶然发现了这个问题(尽管它们在 Firefox 上看起来很好)。
2021-05-11 07:13:58
@Martin:我相信只有在没有设置(某种回退机制)的情况下才会发生这种情况。至少这是我记得的(我通读了这段代码)。顺便提一句。toLocaleString(langTag) 将是未来格式化日期的最佳方式
2021-05-11 07:13:58

要将时间转换为服务器上特定于语言环境的字符串,您可以使用DateTime.ToLongDateString方法在该页面上,请参阅有关DateTimeFormatInfo类的“当前区域性对象”(在服务器上)的注释确保设置正确。

任何答案都没有解决这个问题的根本原因。OP 说:

我正在2012-11-13T04:45:00.00以 GMT 格式从服务器接收类似这样的数据时间

GMT 不是一种格式。此字符串采用 ISO 8601 扩展格式,未指定任何时区。ISO 8601 规范说,如果没有限定符,这旨在表示local time要指定 GMT,您可以Z在末尾附加 a ,或者您可以附加一个偏移量,例如+00:00.

问题是,ECMAScript (v1 - v5.1) 没有遵守规范中的这一规定。它实际上说应该解释为UTC而不是本地时间。一些浏览器遵守 ISO 规范,一些浏览器遵守 ECMA 规范。这已在第 6 版中得到纠正,并且大多数浏览器都已遵守。

所以 - 如果您打算传输基于 UTC/GMT 的时间戳,那么在服务器端,您应该始终发送 aZ以便没有歧义。

尽管如此,即使正确解释了该,也不能保证字符串在不同浏览器中的格式相同。为此,您确实需要一个库。我推荐moment.js,但还有其他的。