【问题标题】:Detect timezone abbreviation using JavaScript使用 JavaScript 检测时区缩写
【发布时间】:2010-12-29 14:10:33
【问题描述】:

我需要一种方法来检测给定日期对象的时区。我不想要偏移量,也不想要完整的时区名称。我需要获取时区缩写。

例如,GMT、UTC、PST、MST、CST、EST 等...

这可能吗?我得到的最接近的是解析date.toString() 的结果,但即使这样也不会给我缩写。它给了我时区的长名称。

【问题讨论】:

标签: javascript date timezone


【解决方案1】:

原生解决方案:

var zone = new Date().toLocaleTimeString('en-us',{timeZoneName:'short'}).split(' ')[2]
console.log(zone)

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString

您可以传递 undefined 而不是 en-us 以默认为浏览器的当前语言环境。

【讨论】:

  • 这给了我 GMT+10,而不是 AEST。然而,长版给了我澳大利亚东部标准时间。这是在运行 Chrome 的 Mac 上。
  • 为什么我们需要输入“en-us”?如果我从不同的时区运行会影响吗?
  • @GokulanPH 使用任何东西,但在其他本地化中,时区可能被称为其他东西。老实说,我不知道,请与您当地的人一起尝试,如果结果不同,请告诉我们。
  • 这在 IE11 中不起作用,它在 IE11 中返回“未定义”,还有其他适用于所有浏览器的解决方案吗?
  • 过去几个月的某个时候,在 Chrome 中,这开始返回“GMT-6”而不是 EST/CST/PST 等。过去可以正常工作。
【解决方案2】:

moment-timezone 包含一个未记录的方法.zoneAbbr(),它返回时区缩写。这还需要一组可根据需要选择和下载的规则。

这样做:

<script src="moment.js"></script>
<script src="moment-timezone.js"></script>
<script src="moment-timezone-data.js"></script>
<script>
    moment().tz("America/Los_Angeles").zoneAbbr();
</script>

返回:

'PDT' // As of this posting.

编辑(2018 年 2 月)

Evan Czaplicki 曾在 a draft proposal to add a time zone API to browsers 工作。

【讨论】:

  • 是的,但是一开始就知道当地时区是一个挑战。见stackoverflow.com/a/18252251/634824
  • 好点。我也使用jsTimeZoneDetect。但是,正如您在链接中提到的那样,我正在考虑切换到在用户个人资料中设置时区。
  • 在我的几个项目中,我使用both。我让 jstz 检测一个初始值,但我让用户更改它。当然,您的要求可能会有所不同。
【解决方案3】:

Date 对象没有获取时区缩写的方法,但它隐含在 toString 结果的末尾。例如,

var rightNow = new Date();
alert(rightNow);

...将返回类似Wed Mar 30 2011 17:29:16 GMT-0300 (ART) 的内容。时区缩写可以用括号隔开:

var rightNow = new Date();
alert(String(String(rightNow).split("(")[1]).split(")")[0]);

输出将是时区缩写,例如 ART

【讨论】:

  • 不错的答案,但对于那些使用它的人来说......它不适用于所有浏览器。不同浏览器的格式化日期字符串可能不同。
  • 为什么JS Date这么乱? new Date();铬=Wed May 07 2014 09:20:32 GMT-0500 (UTC)。火狐=2014-05-07T14:20:54.371Z。 Safari = Wed May 07 2014 09:21:49 GMT-0500 (CDT).
  • @ShaneStillwell 您的投诉似乎与date.toString() 有关,这是您在创建new Date() 时在控制台中看到的内容。 toString() 的规范将其描述为依赖于实现,这似乎是不使用此答案的好理由。
  • 在 Chrome 中,它会为我写完整的日期,而不是缩写版本。虽然获得人类可读的时区标签仍然很整洁。
【解决方案4】:

这在 Chrome、Firefox 中完美运行,但主要在 IE11 中运行。在 IE11 中,没有像“Indian Chagos Time”这样直接缩写的时区将返回“ICT”而不是正确的“IOT”

var result = "unknown";
try{
    // Chrome, Firefox
    result = /.*\s(.+)/.exec((new Date()).toLocaleDateString(navigator.language, { timeZoneName:'short' }))[1];
}catch(e){
    // IE, some loss in accuracy due to guessing at the abbreviation
    // Note: This regex adds a grouping around the open paren as a
    //       workaround for an IE regex parser bug
    result = (new Date()).toTimeString().match(new RegExp("[A-Z](?!.*[\(])","g")).join('');
}
console.log(result);

结果:

"CDT"

【讨论】:

  • 这个策略最接近我想要的。虽然您在第 4 行有错误(未定义的date),但构造缩写的正则表达式对我来说是一个尽力而为的解决方案。谢谢!
  • 感谢指出错误,我已经更新了sn-p。
【解决方案5】:

2021 年更新

moment.js 现在是 deprecated,他们建议在新项目中使用 Luxon

您可以使用 Luxon 获得时区缩写,例如:

import { DateTime } from 'luxon'
DateTime.local().toFormat('ZZZZ') // => for ex: "PDT"

注意:输出格式取决于设置的语言环境。如需更多信息,请参阅this answer

【讨论】:

    【解决方案6】:

    我只需要片刻就能做到这一点。

    moment.tz(moment.tz.guess()).zoneAbbr() //IST
    

    【讨论】:

    • 添加一些解释,说明此答案如何帮助 OP 解决当前问题
    【解决方案7】:

    使用来自new Date().toString()的内容

    const timeZoneAbbreviated = () => {
      const { 1: tz } = new Date().toString().match(/\((.+)\)/);
    
      // In Chrome browser, new Date().toString() is
      // "Thu Aug 06 2020 16:21:38 GMT+0530 (India Standard Time)"
    
      // In Safari browser, new Date().toString() is
      // "Thu Aug 06 2020 16:24:03 GMT+0530 (IST)"
    
      if (tz.includes(" ")) {
        return tz
          .split(" ")
          .map(([first]) => first)
          .join("");
      } else {
        return tz;
      }
    };
    
    console.log("Time Zone:", timeZoneAbbreviated());
    // IST
    // PDT
    // CEST

    【讨论】:

    • 新加坡不行,显示“+08”
    【解决方案8】:

    您可以使用Intl.DateTimeFormatformatToParts方法获取短时区缩写。在世界的某些地方,这可能会返回像 "GMT+8" 这样的字符串,而不是实际时区名称的缩写。

    let timeZone = new Intl.DateTimeFormat('en-us', { timeZoneName: 'short' })
      .formatToParts(new Date())
      .find(part => part.type == "timeZoneName")
      .value
    console.log(timeZone)

    【讨论】:

    • @ThirstMonkey 我希望 timeZoneName 为 EST 或 PST。以及您如何知道始终使用“en-us”它也可能是 de-De
    【解决方案9】:

    您可以使用本机 Javascript 日期对象。 只需硬编码长时区名称'America/Los_Angeles

    var usertimezone = 'America/Los_Angeles';
    var usertimezoneabbreviation = new Date().toLocaleTimeString('en-us',{timeZone: usertimezone, timeZoneName:'short'}).split(' ')[2];
    
    console.log(usertimezoneabbreviation); //PDT

    【讨论】:

    • @Mirris 我一般的方式是你如何知道/将“en-us”映射到“America/Los_Angeles”
    • @AnkitPandey en-us 是一个语言环境,'America/Los_Angeles' 是一个时区。他们是两个不同的东西。那里没有映射。如果您的意思是 PDT => 'America/Los_Angeles' 也没有 1:1。见github.com/dmfilipenko/timezones.json/blob/master/…
    【解决方案10】:

    2015 年更新:

    jsTimezoneDetect可以和moment-timezone一起使用获取客户端时区缩写:

    moment.tz(new Date(), jstz.determine().name()).format('z');  //"UTC"
    

    Moment-timezone 无法自行执行此操作,因为它用于处理此问题的函数已被贬值,因为它并非在所有情况下都有效:https://github.com/moment/moment/issues/162 获取客户端时区缩写。

    【讨论】:

      【解决方案11】:

      如果一切都失败了,您可以简单地使用the long names and abbreviations 创建自己的哈希表。

      【讨论】:

      • 这不应该是选择的答案。
      • 答案是在 2009 年选择的。Chrome 直到 2010 年才支持 toLocaleTimeString 选项。Firefox 在 2014 年添加它们,Safari 在 2016 年添加它们。所以......是的。
      • 这不起作用,因为像 America/Los_Angeles 这样的时区可以有两个缩写,具体取决于夏令时是否有效(即 PDT 或 PST)
      • America/Los_Angeles 是太平洋时区的 IANA 标准名称。如果您要处理历史日期,则应始终使用 IANA 标准,因为应该应用夏令时的时间界限已经发生了变化。我看到原始帖子要求专门针对这些别名使用缩写,因此我的评论在这方面没有帮助。
      • 实际上时区名称不是官方的或标准化的。尽管有 IANA 支持,但 tz 数据库由志愿者维护。 “America/Los_Angeles”是该数据库中记录的名称,并伴随着注释“美国太平洋时间,以洛杉矶为代表”。同样来自该数据库文件:“此文件绝不是权威文件;如果您认为自己知道得更多,请继续编辑该文件...”
      【解决方案12】:

      对于跨浏览器支持,我建议使用 YUI 3 库:

      Y.DataType.Date.format(new Date(), {format:"%Z"});
      

      它支持strftime 标识符。

      更多信息: http://yuilibrary.com/yui/docs/datatype/#dates

      【讨论】:

        【解决方案13】:

        我知道问题仍然存在于浏览器之间的差异,但这是我过去在 Chrome 中得到的。但是它仍然不是缩写,因为 Chrome 会返回长名称。

        new Date().toString().replace(/^.*GMT.*\(/, "").replace(/\)$/, "")
        

        【讨论】:

          【解决方案14】:

          原生 JavaScript 无法实现。浏览器在返回时区字符串方面不一致。一些返回偏移量,如+0700,而另一些返回PST

          它不一致或不可靠,这就是为什么您需要像moment.js(和moment-timezone.js)这样的第三方脚本,或者创建自己的哈希表来在偏移量和时区缩写之间进行转换。

          【讨论】:

            【解决方案15】:

            这是一个棘手的话题。从我收集的信息来看,时区在创建时并未嵌入为 Date 对象的一部分。您也不能为 Date 对象设置时区。但是,您可以从 Date 对象中获得一个时区偏移量,该对象由用户的主机系统(时区)设置确定。将时区视为确定与 UTC 的偏移量的一种方式。

            为了让生活更轻松,我强烈推荐momentmoment-timezone 来处理这些事情。 Moment 为 Date 创建了一个包装器对象,并为各种事物提供了一个不错的 API。

            如果通过某些参数或其他东西向您提供现有的日期对象,您可以在创建时刻对象时将其传递给构造函数,然后您就可以滚动了。此时您可以使用moment-timezone 猜测用户的时区名称,然后使用moment-timezone formatting 获取时区的缩写。我敢说大多数用户都自动设置了他们的时区,但你不应该依赖它来获得 100% 的准确性。如果需要,您还可以在提取所需格式之前手动设置要使用的时区。

            通常在使用日期和时间时,最好将 UTC 存储在数据库中,然后在显示时使用 moment js 格式化用户时区的时间。在某些情况下,您可能需要确保时区正确。例如,如果您允许用户在特定日期和时间安排某事。您需要绝对确保与西海岸用户一起将时区设置为 PDT/PST,然后再转换为 UTC 以存储在数据库中。

            关于时区缩写...
            这是一个使用 moment 和 moment-timezone 获取时区缩写的基本示例。

            // if all you need is the user's timezone abbreviation you don't even need a date object.
            const usersTimezoneName = moment.tz.guess()
            const timezoneAbbr = moment().tz(usersTimezoneName).format('z')
            console.log(timezoneAbbr) // PST (depending on where the user is)
            
            // to manually set the timezone
            const newYorkAbbr = moment(dateObj).tz('America/New_York').format('z')
            console.log(newYorkAbbr) // EST
            

            要显示具有特定时区偏移量的特定日期对象,您可以这样做。

            const xmas = new Date('December 25, 2017 16:20:00')
            const losAngelesXmas = moment(xmas).tz('America/Los_Angeles')
            console.log(losAngelesXmas.format("dddd, MMMM Do YYYY, h:mm:ss a")) // Monday, December 25th 2017, 4:20:00 pm
            

            【讨论】:

              【解决方案16】:

              试试这个功能

              function getTimezoneAbbreviation(date) {
                // Convert the date into human readable
                // An example: Fri Jul 09 2021 13:07:25 GMT+0200 (Central European Summer Time)
                // As you can see there is the timezone
              
                date = date.toString();
              
                // We get the timezone matching everything the is inside the brackets/parentheses
                var timezone = date.match(/\(.+\)/g)[0];
              
                // We remove the brackets/parentheses
                timezone = timezone.replace("(", "").replace(")", "");
              
                // A new variable for the abbreviation
                var abbreviation = "";
              
                // We run a forEach dividing the timezone in words with split
                timezone.split(" ").forEach((word) => {
              
                    // We insert the first letter of every word in the abbreviation variable
                    abbreviation += word.split("")[0];
              
                });
              
                // And finally we return the abbreviation
                return abbreviation;
              }
              

              【讨论】:

                【解决方案17】:

                试试 Google 的 Closure Class goog.i18n.DateTimeSymbols 及其与语言环境相关的类。

                【讨论】:

                  【解决方案18】:

                  这是一个 JavaScript 自我更新、12 小时格式的日期/时间显示,它并不能完全回答问题,但它可能会帮助其他人,因为它是相关的,并且建立在 Stephen DuMont's 解决方案和 MDN 链接上。 W3 Schools 有一个非常有用的教程,实时更新不需要刷新页面。

                  使用最新版本的桌面 FireFox、Chrome、Opera 和 Internet Explorer 11 进行测试都可以正常工作。在 IE 中,“2 位”小时似乎只为单个值添加零前缀,但是对于所有浏览器,分钟都可靠地返回 2 位值。尽管忽略了 12 小时格式并且没有隐藏秒数,但使用已停产的 Windows Safari 进行的测试仍然有效。

                  该功能包括本地时区,以及备用语言、日期和日期显示以及 12/24 小时格式的可调选项。拆分日期和时间以添加分隔的“at”字符串。仅使用选择选项设置“toLocaleTimeString”也将返回日期和时间。可以参考 MDN 页面以获取选项和值。

                  <!--
                  function dateTimeClock() {
                    var date = new Date();
                    document.getElementById('timedate').innerHTML = date.toLocaleDateString(['en-us', 'en-GB'], {
                        weekday: 'long',
                        month: 'long',
                        day: '2-digit',
                        year: 'numeric'
                      }) + ' at ' +
                      date.toLocaleTimeString(['en-us', 'en-GB'], {
                        hour12: 'true',
                        hour: '2-digit',
                        minute: '2-digit',
                        timeZoneName: 'short'
                      });
                    var t = setTimeout(dateTimeClock, 500);
                  }
                  
                  function start() {
                    dateTimeClock();
                  }
                  window.onload = start;
                  //-->
                  &lt;div id="timedate"&gt;&lt;/div&gt;

                  【讨论】:

                    【解决方案19】:
                    import { tz } from 'moment-timezone';
                    import * as moment from 'moment';
                    
                    const guess = tz.guess(true);    // "Asia/Calcutta"
                    const zone = tz.zone(guess);     // return Zone object 
                    zone.abbr(new Date().getTime())  // "IST" 
                    // once u pass timestamp it'll return timezone abbrevation.
                    

                    【讨论】:

                    • 你需要导入什么时刻?
                    【解决方案20】:
                    try {
                        result = /.*\s(.+)/.exec(date.toLocaleDateString(navigator.language, {timeZoneName:'short' }))[1];
                    } catch(e) {
                        result = (new Date()).toTimeString().match(new RegExp("[A-Z](?!.*[\(])","g")).join('');
                    }
                    
                    console.log(result);
                    

                    【讨论】:

                    • 降级者是否愿意发表评论
                    • 回答的人会关心对放置的代码有更多的了解,或者这个答案只是传播盲目的代码使用(又名:复制和粘贴是要走的路,给所有非信徒打耳光一个火炬),给予反对票(“降级[原文如此!]”)应该被接受在问答网站上的良好做法。评论够吗?请让我们知道并通过评论分享您的反馈。我们只能努力通过在拥有如此多不同社区的互联网论坛上提供的所有多样性交流和社交互动来提高可用性。
                    猜你喜欢
                    • 2020-09-13
                    • 2021-04-01
                    • 2017-01-29
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-07-20
                    • 2012-05-18
                    相关资源
                    最近更新 更多