【问题标题】:Wrong locale time in Android webviewAndroid webview中错误的语言环境时间
【发布时间】:2019-03-10 20:43:34
【问题描述】:

我们有一个 Android 应用程序,它或多或少只包含一个 web 视图,显示一个 web 应用程序。在某些时候,我们想向用户显示一些时间戳并使用以下代码

let dateString = new Date().toLocaleTimeString();

问题是,即使我们将设备设置为使用 24 小时时钟(并且设备确实尊重这一点设置,因为我们在状态栏中看到了正确的时间)。我们还将设备设置为使用德语并删除了英语设置。也没有运气。使用了设备区域设置,因为我们的应用程序以正确的语言显示,但时间字符串仍然错误。

window.navigator.language  -> "de-AT"
new Date().toLocaleTimeString(); -> "6:10:13 PM"
new Date().toLocaleTimeString(window.navigator.language); -> "18:10:32"

乍一看,最后一行似乎是一种可能的解决方法,但如果语言是例如“en-US”,则无论操作系统是否配置为使用 24 小时时钟,这将始终返回 12 小时格式。

我知道this 问题,这似乎与这个问题有某种关系,但答案对我们不起作用。

使用我发现的各种虚拟设备,它在 chrome 58(在 API 26 上)上仍然可以正常工作,但在 chrome 61(在 API 27 上)上不再工作。目前在 chrome 70 beta 进行测试,问题依然存在。

还需要注意的是,它在 chrome 本身中可以正常工作(即,如果我在测试网站中显示时间戳,它会使用系统设置),但只会在 webview 中失败。

我们当前的解决方法是通过本机应用程序生成时间戳,但这似乎相当笨拙。

更新

我知道我可以在 webapp 端做一些事情,比如覆盖 toLocaleTimeString(事实上,我已经这样做了,以从本机应用程序中获取正确的格式)。

我的问题更多是关于:在本机 WebView 中是否有任何已知的更改行为(可能还有一个反转此设置)导致此问题发生,因为这在 Chrome 设备上工作/工作就像一个魅力

与此同时,我向 Chromium 提交了一个问题,他们能够重现它。也许这会在下一个版本中得到修复......

更新 2

这个问题已经在谷歌方面得到解决,并且可能会在未来的一些更新中推出。与此同时,我将继续使用我当前对toLocaleTimeString() 的覆盖,它会回调本机应用程序...

【问题讨论】:

  • 好吧,我知道确切的输出格式取决于实现。但它至少应该以某种方式反映正确的语言环境,而不是总是使用 en-US。它在使用相同代码的 chrome 浏览器中运行。如果我将语言环境定义为参数,它就可以工作(有点)。因此,假设这是 webview 初始化的问题,这是非常可靠的。
  • 来自规范:“此函数返回一个字符串值。字符串的内容取决于实现,但旨在表示当前时区中日期的“时间”部分方便的、人类可读的形式,对应于宿主环境当前语言环境的约定”。我知道这不是输出的确切规范,但在我看来,在 de-DE 系统上输出 en-US 约定是违反规范的。特别是如果同一产品在另一个环境中的行为不同
  • 很公平,如果你不喜欢输出就不要使用 localeString()s...
  • 我想要输出,如果它表现得像指定的那样。我也有一个解决方法,我觉得它相当笨拙。此外,这可以按预期工作,直到至少 58 版的 chrome。因此,我真的认为这是一个问题(除非有人指出解释了这种行为变化的官方文件),我的问题的目的是找出其他人是否偶然发现并解决了这个问题,而不是替换每一次出现的 @987654329 @
  • 你可以重新定义方法。例如:Date.prototype.toLocaleTimeString = function(){return String(this).bold();}; new Date().toLocaleTimeString(); // has bold tags 使用类似 moment.js 的东西。您也可以使用 toISOString() 获得 24 小时版本,但您需要先将日期偏移当地时区偏移量,这需要一点数学但并不困难。

标签: javascript android google-chrome webview locale


【解决方案1】:

请尝试覆盖函数 Date.prototype.toLocaleTimeString

let f = Date.prototype.toLocalString;

Date.prototype.toLocalString = function(){
  let s = f();
  //since the method fails for US-locale manupulate s as required when locale is US and system is set to show 24 hr 
  
  // if ends with AM - just delete "AM"
  // if ends with PM - add 12 to hr and delete "PM"
  return s;
}
---请避免直接修改内置JS对象的原型--- 我还要指出,不建议使用 JS 的内置对象,因为它可能会破坏或中断某些外部库的执行。所以最好创建一个新对象并修改该对象的原型 - 使用原型继承。

【讨论】:

  • 抱歉,不行。我想要一个反映系统设置的 localeString,即当 android 设备设置为 24 小时制时获得 24 小时制,当 android 设备设置为 12 小时制时获得 12 小时制。您的建议始终提供 24 小时时间,而且对于 12:00 AM(即 24 小时制中的 00:00 而不是 12:00)和下午 12:00(即 24 小时制中的 12:00 而不是24:00)。
  • 感谢您的指出。很抱歉没有把答案说得很清楚。 1. FOCUS - 尝试覆盖该方法。 2.我已经明确写了,只修改日期的时候a。区域设置是日期不反映系统格式(在本例中为美国区域设置)和 b。当系统设置为 24 小时时。
  • 由于您似乎是一个非常高级的程序员,所以我还要指出,不建议使用 JS 的内置对象,因为它可能会破坏或中断某些外部库的执行。所以最好创建一个新对象并修改该对象的原型 - 使用原型继承。
  • 尝试设置 webchrome 客户端和 webview 客户端。不确定它是否对您有帮助。 myWebView.setWebChromeClient(new WebChromeClient());
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
相关资源
最近更新 更多