【问题标题】:Creating new date object which includes timezone identifier创建包含时区标识符的新日期对象
【发布时间】:2014-04-03 03:00:19
【问题描述】:

我正在从 Facebook 的 API 查询活动开始时间。大多数情况下,它们返回如下字符串:

2014-04-02T20:00:00-0600

但有时,它的返回如下:

2014-04-19

当我尝试创建一个新的日期对象时,它不适用于时区标识符。

但是,这两种方法都有效:

var d = new Date('2014-04-02T20:00:00')

var d = new Date('2014-04-19')

但我需要这个来工作:

var d = new Date('2014-04-02T20:00:00-0600')
// returns Invalid Date

我正在尝试避免解析每个 start_time 字符串以查看是否需要删除时区标识符,因为我正在处理数百个事件。

有没有更简单的方法来做我正在尝试的事情,还是我真的需要删除每个日期的时区标识符?

【问题讨论】:

  • 这对engineering.nulogy.com/posts/…有帮助吗?
  • 您需要“手动”解析字符串。这并不难,您只需编写一次代码。但你确实需要明确地说出你想做什么。您想将 2014-04-02T20:00:00-0600 转换为用户的本地时间,还是以特定时区(例如 UTC)显示它?
  • 你试过使用 timestamptz 类吗?
  • @jp310 是的,这是一些有用的信息。我试图避免使用 moment.js 库。但我会考虑的。
  • @RobG 是的,我知道这并不难。如果我想对偏移量做任何事情,这是一个很好的见解。

标签: javascript facebook iso


【解决方案1】:

您可以使用以下方法解析带有偏移量的 ISO 8601 字符串。如果字符串没有偏移量,则假定为 Z(即ECMA-262 的 UTC):

/* Parse an ISO string with an offset
**   e.g. '2014-04-02T20:00:00-0600'
**        '2014-04-02T20:00:00Z'
**
** Allows decimal seconds if supplied
**   e.g. '2014-04-02T20:00:00.123-0600'
**
** If no offset is supplied (or it's Z), treat as UTC (per ECMA-262)
** If date only, e.g. '2014-04-02', treat as UTC date (per ECMA-262)
*/
function parseISOString(s) {
  var t = s.split(/\D+/g);
  var hasOffset = /\d{2}[-+]\d{4}$/.test(s);

  // Whether decimal seconds are present changes the offset field and ms value
  var hasDecimalSeconds = /T\d{2}:\d{2}:\d{2}\.\d+/i.test(s);
  var offset = hasDecimalSeconds? t[7] : t[6];
  var ms = hasDecimalSeconds? t[6] : 0;
  var offMin, offSign, min;

  // If there's an offset, apply it to minutes to get a UTC time value
  if (hasOffset) {
    offMin = 60 * offset / 100 + offset % 100;
    offSign = /-\d{4}$/.test(s)? -1 : 1;
  }
  min = hasOffset? +t[4] - offMin * offSign : (t[4] || 0);

  // Return a date object based on UTC values
  return new Date(Date.UTC(t[0], --t[1], t[2], t[3]||0, min, t[5]||0, ms));
}

// Tests
console.log(parseISOString('2014-04-02T20:00:00-0600').toISOString());    // 2014-04-03T02:00:00.000Z
console.log(parseISOString('2014-04-02T20:00:00Z').toISOString());        // 2014-04-02T20:00:00.000Z
console.log(parseISOString('2014-04-02T20:00:00').toISOString());         // 2014-04-02T20:00:00.000Z
console.log(parseISOString('2014-04-02T20:00:00.123-0600').toISOString());// 2014-04-03T02:00:00.123Z
console.log(parseISOString('2014-04-02T20:00:00.123').toISOString());     // 2014-04-02T20:00:00.123Z
console.log(parseISOString('2014-04-02').toISOString());                  // 2014-04-02T00:00:00.000Z

请注意,如果这将根据系统设置创建一个带有主机环境时区偏移量的日期对象。 Date 的时间值将是所提供时间戳的等效 UTC 时间(在本例中为“2014-04-03T02:00:00Z”)。您可以使用 toISOString 方法确认(需要 IE9 或更高版本,或其他现代浏览器)。

编辑

请注意,您不能设置 Date 对象的时区偏移量。它们具有表示 UTC 时刻的时间值和基于系统设置的时区偏移量。您可以使用标准日期方法(例如 getFullYeargetHours)读取“本地”日期和时间值,如果使用 UTC 方法(例如 getUTCFullYear),则可以读取 UTC 值>,获取UTCHours)。

编辑 2

允许仅日期格式(将其视为 UTC)。

【讨论】:

  • 我喜欢这里的发展方向。但是,如问题中所述,有时事件的 start_time 格式如下:2014-04-19 在这种情况下会失败。我想虽然我可以在遇到带有标识符的 start_time 时使用它。
  • 我添加了对仅日期格式的支持,它被视为 UTC。那是你需要的吗?很容易将其视为本地日期。
  • 太棒了,感谢您的宝贵时间。这样做比包含一个库要好得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-03
  • 2014-10-16
  • 1970-01-01
相关资源
最近更新 更多