使用 javascript 检测用户设备的时钟制式,是12小时制(上午/下午)还是24小时制(军用时间)。

22

有没有可能检测用户的机器是使用12小时制(am/pm)还是24小时制(军事时间)?

一种方法是检查用户的语言环境,但这只是大量语言环境比较的列表,来自美国并希望使用12小时制的人可以向我发送en语言环境,而不是US_en,我无法知道她的偏好。同时,来自美国的某些人可能将他们的机器设置为使用12小时制时间格式,但不想要12小时制时钟。

编辑:

date.toLocaleTimeString();

作为用户Mouser在下面建议的理论上是可行的,但不幸的是,在WebKit浏览器上(在Windows上测试过Chrome和新Opera),它存在错误,并且由于某种原因始终返回am / pm时间。

例如:http://jsfiddle.net/sjuaL3p4/

所以我猜我必须重新表达我的问题,如果有人有想法如何在Webkit浏览器上实现它。


你想知道用户在其操作系统中的偏好设置,以便你的浏览器代码可以与用户的操作系统偏好相同吗? - Louis
1
@Louis 是的,那正是我想要的。 - Badr Hari
1
Windows 7,Firefox 34.0.5; .toLocaleTimeString() 显示12小时制时间,无论我的设置如何。 - Hydrothermal
6个回答

11
你可以使用 resolvedOptions 和国际化API来确定 hourCycle:
const locale = navigator.language
Intl.DateTimeFormat(locale,  { hour: 'numeric' }).resolvedOptions().hourCycle // ?
Intl.DateTimeFormat('en-US', { hour: 'numeric' }).resolvedOptions().hourCycle // h12
Intl.DateTimeFormat('en-GB', { hour: 'numeric' }).resolvedOptions().hourCycle // h23

这并没有说明系统实际设置是什么,它只是根据浏览器语言设置进行猜测(可能与系统语言不同,并且不一定反映时间格式设置)。此外,hourCycle 是错误的选项,应该是 hour12(true/false)或 dayPeriod(am/pm)。 - RobG
您的浏览器应该从操作系统设置中获取区域设置,但是根据您的观点,这可能会变得复杂。例如,操作系统区域设置为 en-US,但您也喜欢 h23 时间格式。我不认为浏览器目前有一种方法可以检测到这一点。我已经有几年没有研究过它了,所以如果有什么变化,我会很好奇的。使用 hour12 也可以,但我不建议使用 dayPeriod,因为只有 Safari 似乎返回该属性。 - kgreen
toLocaleString 生成的格式基于语言代码(“区域设置”)、提供的选项和名义上来自 CLDR 项目 的数据。它们不是(也不能)基于系统设置,因为特定的实现应该为相同的语言和选项生成相同的格式,而不管主机系统如何。否则,如果更多或更少地被系统设置随意覆盖,指定特定语言和选项的开发人员将不知道可能产生什么格式。 - RobG
遗憾的是,navigator.language 是很复杂的 - Safari 在确定其 navigator.language 值时将使用操作系统的语言设置。而 Chrome 和 Firefox 都有自己的内部语言配置,它们从中提取信息。 - kgreen

9

这个解决方案在大多数浏览器中都有效,但在Chrome浏览器中出现了错误。

    var date = new Date(Date.UTC(2012, 11, 12, 3, 0, 0));
    var dateString = date.toLocaleTimeString();

    //apparently toLocaleTimeString() has a bug in Chrome. toString() however returns 12/24 hour formats. If one of two contains AM/PM execute 12 hour coding.
    if (dateString.match(/am|pm/i) || date.toString().match(/am|pm/i) )
    {
        //12 hour clock
        console.log("12 hour");
    }
    else
    {
        //24 hour clock
        console.log("24 hour");
    }

Chrome的解决方案; 概念验证

这是Chrome的一个丑陋解决方案。它通过反向地理定位来探测用户的国家代码。该代码会与使用12小时制的国家数组进行比较。这种解决方案很丑陋,因为你需要用户许可才能获取地理位置数据,如果用户的语言环境不同,它将提供错误的信息,但仍能提供用户所在的国家。 我强烈建议不要使用此示例。它纯粹是为了启发目的而编写的概念验证。

 function getClockChrome() {

  navigator.geolocation.getCurrentPosition(function(pos) {
   var url = "http://nominatim.openstreetmap.org/reverse?format=json&lat="+pos.coords.latitude+"&lon="+pos.coords.longitude+"&addressdetails=1&accept-language=en_US&json_callback=chromeClockCallBack";
   var script = document.createElement('script');
   script.src = url;
   document.body.appendChild(script);
  },
  
  function()
  {
   //no access to location
  },
  

  {
    enableHighAccuracy: true,
    timeout: 5000,
    maximumAge: 0
  }
  );

 }

 getClockChrome();

 var dateCountryCode = ['US', 'GB', 'PH', 'CA', 'AU', 'NZ', 'IN', 'EG', 'SA', 'CO', 'PK', 'MY'];
 function chromeClockCallBack(data)
 {
        //Request succeeded
  if (dateCountryCode.indexOf(data.address.country_code.toUpperCase()) > -1)
  {
   alert("12 hour clock");
  }
  else
  {
   alert("24 hour clock");
  }
 }


2
http://jsfiddle.net/sjuaL3p4/ - 我正在使用24小时制的钟表,但toLocaleTimeString返回AM/PM时间...我认为您需要指定要使用的语言环境,但这会失去其目的... - Badr Hari
@BadrHari我不知道职业拳击手也能编写代码,但我已经进行了编辑,可能适用于所有浏览器。 - Mouser
虽然我本来想避免使用地理定位,但由于 Webkit 的 bug,看来我不得不朝这个方向去了。感谢你和我一起思考这个问题。 - Badr Hari
2
这种方法不可靠,因为toLocaleString的实现依赖于具体情况,可能反映系统设置,也可能不反映。在MacOS和Safari上,无论我将系统时间格式设置为什么,输出始终是“24小时”,而Firefox始终是“12小时”。 - RobG
如果用户所处的时区在一天中的前12个小时(上午而不是下午)有硬编码时间,这不会失败吗? - Justin
显示剩余3条评论

2

toLocaleTimeString 应该按照用户的偏好以特定格式显示时间,但它并不可靠。

我在一个 Debian 系统上。运行 locale 命令的输出为:

LANG=en_US.utf8
LANGUAGE=
LC_CTYPE="en_US.utf8"
LC_NUMERIC="en_US.utf8"
LC_TIME="en_US.utf8"
LC_COLLATE="en_US.utf8"
LC_MONETARY="en_US.utf8"
LC_MESSAGES="en_US.utf8"
LC_PAPER="en_US.utf8"
LC_NAME="en_US.utf8"
LC_ADDRESS="en_US.utf8"
LC_TELEPHONE="en_US.utf8"
LC_MEASUREMENT="en_US.utf8"
LC_IDENTIFICATION="en_US.utf8"
LC_ALL=

这里有几个关于日期的实验:
$ date +%X
05:23:32 PM
$ LANG=en_GB date +%X
17:24:06
$ LC_TIME=en_GB date +%X
17:24:22

%X格式告诉date根据本地语言输出时间。以上结果正如所预期的一样。设置LC_TIME是一种仅更改时间格式但保持其余语言环境不变的方法。因此,即使默认设置为12小时制,美国用户也可以使用24小时制。

我在我的系统上尝试了Mouser's脚本:

$ firefox --no-remote
[Shows a time in the 12 hour format, as expected.]
$ LANG=en_GB firefox --no-remote
[Shows a time in the 24 hour format, as expected.]

到目前为止一切都很好。然而,
$ LC_TIME=en_GB firefox --no-remote
[Shows a time in the 12 hour format, this is wrong!]

我在使用Chrome时得到了相同的结果。看起来Firefox和Chrome都忽略了LC_TIME

1
除了这一点不应该做,即使它在所有浏览器中都有效,.toLocaleTimeString()也不是一个好的解决方案。它返回一个遵循用户计算机设置格式的时间字符串,但可能存在一个仍显示上午/下午的24小时时钟,以及一个不显示上午/下午的12小时时钟。准确可靠地检测这一点是不可行的。

0

这对我在Chrome中有效。我使用了@Mouser的选定答案,但在Chrome中无法正常工作。

    let result = false;
    const date = new Date();
    const dateString = date.toLocaleTimeString(language, {
        timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
        timeStyle: 'short'
    });
    
    if (dateString.match(/am|pm/i) || date.toString().match(/am|pm/i)) {
        result = true;
    }
    else {
        result = false;
    }

0

这个简单的代码行对我来说似乎有效。

var is24 = ((new Date(2014, 01, 01, 15, 0, 0, 0)).toLocaleTimeString().indexOf("15") > -1);

虽然它在Chrome中仍然无法工作(在IE和Firefox中可以工作)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接