【问题标题】:How do I compare a JavaScript date against a date in a specific timezone?如何将 JavaScript 日期与特定时区的日期进行比较?
【发布时间】:2018-02-10 01:08:36
【问题描述】:

我想看看当前时间是否大于山区时间本周一下午 5:00,不管这段代码在哪个时区运行。我有这样的事情:

function isAfterMondayEvening() {
  var now = new Date();
  var mondayEvening = dateFns.setHours(dateFns.setDay(now, 1), 17);
  return dateFns.compareAsc(now, mondayEvening);
}

console.log(isAfterMondayEvening());
<script src="//cdn.rawgit.com/date-fns/date-fns/a0005af7d1c3f70c88b8e619bfdff4bf85122863/dist/date_fns.js"></script>

如果正在运行的服务器或浏览器位于不同的时区,那么它会将时间与所在时区的星期一 5 点进行比较。无论这段代码在哪个时区运行,我都想在山区时间与星期一下午 5 点进行比较。我该怎么做?

【问题讨论】:

  • 你试过用 React.js 做这个吗?

标签: javascript date timezone


【解决方案1】:

如果您喜欢 IE 10+,请使用 luxon (https://moment.github.io/luxon/index.html)

function isAfterMondayEvening() {
  const currentTime = luxon.DateTime.local().setZone('America/Denver');
  const mondayEvening = currentTime.set({weekday: 1, hour: 17}).startOf('hour');
  return currentTime > mondayEvening;
}

【讨论】:

    【解决方案2】:

    我使用的一种方法是将两个日期都标准化为 GMT。假设您的服务器日期已经是 GMT,您可以通过减去时区偏移量将浏览器时间转换为 GMT。

    例如,我使用的是大西洋标准时间 (GMT+4)。为了像我在 GMT 一样获得当前时间,我使用以下公式:

    2018-02-09T15:00:00+0400 - (4 * 60 * 60 * 1000) = 2018-02-09T15:00:00Z`
    

    ...其中 4 是以小时为单位的偏移量。

    具体在 JS 中:

    const browserOffset = new Date().getTimezoneOffset();
    const timeFromServer = getTimeFromServer();
    const currentTimeAsGmt = new Date(Date.now() - (browserOffset * 60 * 1000));
    
    // Now compare timeFromServer (already in GMT) to currentTimeAsGmt
    

    在 JS 中,Date#getTimezoneOffset分钟 为单位返回偏移量,所以我省略了一个额外的 * 60

    【讨论】:

    • 日期为 UTC。要获得等效的 UTC 时间戳,请使用 toISOString 或手动格式化的 UTC 方法。
    【解决方案3】:

    假设您可以计算出本周星期一的年/月/日索引,我认为您可以在没有库的情况下做到这一点。诀窍是用 UTC 表示您已知的山区时间:

    let utcMonday = new Date(Date.UTC(2018, 2 - 1, 5, 24));
    let cstDate = new Date();
    let currentTimeGreater = cstDate > utcMonday;
    
    // The rest isn't needed, but shows some console logs of what is going on
    
    let locale = "en-US";
    let timeFormatOptions = {
      weekday: "short",
      hour: "numeric",
      minute: "numeric",
      timeZoneName: "long",
      timeZone: "America/Denver"
    };
    
    let formattedMountainMonday = utcMonday.toLocaleDateString(
      locale,
      timeFormatOptions
    );
    
    let formattedCurrentTime = cstDate.toLocaleDateString(
      locale,
      timeFormatOptions
    );
    
    console.log(formattedMountainMonday);
    console.log(
      `Current time in relation to Mountain time: ${formattedCurrentTime}`
    );
    console.log(
      `Current time is greater than this week's Mountain Monday at 5:00 PM: ${currentTimeGreater}`
    );
    

    【讨论】:

      【解决方案4】:

      美国山区时间 (MT) 偏移量为 -0700。 Javascript 日期本质上是 UTC,因此您需要做的就是将内部 UTC 时间值与 MT 进行比较。通过“本周的星期一”,我假设您希望在星期日和星期一 17:00 之前为 true。如果您只是指星期一,请删除 d.getUTCDay() == 0 || 部分。

      function isBefore1700MT(date) {
      
        // Copy date so don't affect original
        var d = new Date(date);
      
        // Adjust internal UTC to MT
        d.setUTCHours(d.getUTCHours() - 7);
      
        // Return true if the UTC day is Sunday or Monday before 17:00
        return d.getUTCDay() == 0 || (d.getUTCDay() == 1 && d.getUTCHours() < 17);
      }
      
      // Test using current local date and time
      var date = new Date();
      console.log(date.toString() + ' : ' + isBefore1700MT(date));

      【讨论】:

      • 美国山区时间在一年中的部分时间仅偏移 7 小时。在夏令时期间,它有 6 小时的偏移量。请注意,如果您使用此脚本,它可能会在一年中的部分时间返回不正确的结果。
      • @Aaronius — 并非山地时间地区的所有地方都遵守夏令时(例如亚利桑那州的大部分地区)。在夏令时期间,称为山地夏令时 (MDT),否则称为山地标准时间或简称为山地时间。
      【解决方案5】:

      当您说“山区时间”时,您是一直在谈论山区标准时间,还是想同时考虑山区夏令时间?如果您一直在谈论山区标准时间,则可以忽略我的回答,因为您的情况更简单。我将解决您也想考虑山区夏令时的可能性,这是一个更复杂的问题。

      如果您将夏令时考虑在内,请记住并非山地时区内的每个地方都遵守山地夏令时,因此您实际上需要知道山地时区内的位置(例如,是亚利桑那州还是犹他州?)。一旦知道这一点,您就需要像 Moment Timezone 这样具有足够时区信息的库。然后,您必须找到最准确的 tz database timezone name 并使用它,在 Moment Timezone 的帮助下计算出“本周星期一,该特定位置的山区时间下午 5:00”的实际 UTC 时间。您的代码将如下所示:

      // Use whatever time and timezone you're trying to compare with.
      const targetDate = moment()
        .tz('America/Denver')
        .day(1) // Monday
        .hour(17) // 5pm
        .minute(0)
        .second(0)
        .millisecond(0)
        .toDate();
      
      if (new Date() > targetDate) {
        console.log('after target time');
      } else {
        console.log('before target time');
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-30
        • 2017-05-15
        • 1970-01-01
        • 2012-09-26
        • 2014-05-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多