javascript - 使用 JavaScript 从 Apple 收据验证服务器解析日期

标签 javascript date momentjs

我有来自 Apple 收据验证服务器的日期时间。我需要将它与今天的日期进行比较。我正在尝试使用 moment.js,但我也可以使用原生 Date

日期格式是这样的,在什么Apple's docs claim ,incorrectly , 是 RFC 3339 格式:

2017-11-28 23:37:52 Etc/GMT

由于这不是有效的 RFC 3339 或 ISO 8601 日期时间,因此无法使用 moment.js 或 Date.parse() 进行解析。我该如何解析它?

请注意,我不想简单地去掉 Etc/,因为它对于根据 https://opensource.apple.com/source/system_cmds/system_cmds-230/zic.tproj/datfiles/etcetera 确定正确的时区很重要。 :

We use POSIX-style signs in the Zone names and the output abbreviations, even though this is the opposite of what many people expect. POSIX has positive signs west of Greenwich, but many people expect positive signs east of Greenwich. For example, TZ='Etc/GMT+4' uses the abbreviation "GMT+4" and corresponds to 4 hours behind UTC (i.e. west of Greenwich) even though many people would expect it to mean 4 hours ahead of UTC (i.e. east of Greenwich).

最佳答案

您可以采用以下两种策略之一:

  1. 手动解析字符串并使用 Date 构造函数的部分,然后调整时区。
  2. 将时间戳转换为大多数使用中的浏览器应支持的字符串(即符合 ECMA-262 的 ISO 8601 扩展格式)。

第一种方式更健壮。

引用文献没有说明像 +0530 这样的时区是如何以 Etc/格式表示的,所以下面不涉及它们:

  • 'Etc/GMT' 变为 '+00:00'
  • 'Etc/GMT+4' 变成 '-04:00'
  • 'Etc/GMT-10' 变为 '+10:00'

此外,以下函数不验证格式,它们假定提供的字符串是合适的。

// Parse strings in format 2017-11-28 23:37:52 Etc/GMT
function parsePOZIX(s) {
  var b = s.split(' ');
  // These are the date and time parts
  var c = b[0].split(/\D/).concat(b[1].split(/\D/));
  // Create a new Date using UTC
  var d = new Date(Date.UTC(c[0],c[1]-1,c[2],c[3],c[4],c[5]));
  
  // Now adjust for the timezone
  var tz = b[2].split('/')[1];
  var sign = /^\+/.test(tz) ? 1 : -1;
  var hr = tz.replace(/\D/g, '') || '0';
  d.setUTCHours(d.getUTCHours() + sign*hr);
  return d;
}

['2017-11-28 23:37:52 Etc/GMT',
'2017-11-28 23:37:52 Etc/+8',
'2017-11-28 23:37:52 Etc/-10'].forEach(function(s){
  console.log(s + '\n' + parsePOZIX(s).toISOString());
});

第二种(不太可靠的方法)解析并重新格式化字符串,然后使用内置解析器:

// Reformat strings like 2017-11-28 23:37:52 Etc/GMT 
// to ISO 8601 compliance, then use built-in parser
function parsePOSIX2(s) {
  var b = s.split(' ');
  var tz = b[2].split('/')[1];
  var sign = /^\+/.test(tz)? '-' : '+';
  var hr = tz.replace(/\D/g,'') || '0';
  hr = ('0' + hr).slice(-2) + ':00'; // Must include colon for Safari
  return new Date(b[0] + 'T' + b[1] + sign + hr);
}

['2017-11-28 23:37:52 Etc/GMT',
 '2017-11-28 23:37:52 Etc/-4'].forEach(function(s) {
  console.log(s + '\n' + parsePOSIX2(s).toISOString());
});

请注意,Safari 不会解析像“+0000”这样的时区(导致无效日期),它必须包含一个冒号:“+00:00”。

关于javascript - 使用 JavaScript 从 Apple 收据验证服务器解析日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47562083/

相关文章:

javascript - 为什么不能在我的 p5 函数中全局引用这些变量?

javascript - 使用 Javascript 将日期字符串格式化为所需格式

mysql - SQL查询以获取同一天的记录

momentjs - 时区和日期转换问题

javascript - 如何在 ember helper 中将 UTC 时间转换为 momentjs 中指定的格式

javascript - 如何在每次 ng 服务构建后链接 npm 脚本调用?

php - 使用PHP导出XML,通过AJAX将其拉入DOM,但xml不可见

javascript - 修改ng表

ruby-on-rails - 我可以/应该如何处理 RoR 'datetime' "type"/"field"?

javascript - 导入 moment.js 部分或函数