使用JavaScript解析来自Apple收据验证服务器的日期

使用JavaScript解析来自Apple收据验证服务器的日期,javascript,date,momentjs,Javascript,Date,Momentjs,我有苹果收据验证服务器的日期时间。我需要把它和今天的日期比较一下。我正在尝试使用momente.js,但我也可以使用nativeDate 日期的格式如下,在什么声明中,是RFC 3339格式: 2017-11-28 23:37:52 Etc/GMT 由于这不是有效的RFC 3339或ISO 8601 datetime,因此无法使用矩.js或Date.parse()进行解析。我如何解析它 请注意,我不想简单地去掉Etc/,因为它对于根据以下内容确定正确的时区很重要: 我们在区域名称和输出缩写中使

我有苹果收据验证服务器的日期时间。我需要把它和今天的日期比较一下。我正在尝试使用momente.js,但我也可以使用native
Date

日期的格式如下,在什么声明中,是RFC 3339格式:

2017-11-28 23:37:52 Etc/GMT
由于这不是有效的RFC 3339或ISO 8601 datetime,因此无法使用矩.js或
Date.parse()
进行解析。我如何解析它

请注意,我不想简单地去掉
Etc/
,因为它对于根据以下内容确定正确的时区很重要:

我们在区域名称和输出缩写中使用POSIX样式的符号,尽管这与许多人的预期相反。POSIX在格林威治以西有积极迹象,但许多人预计在格林威治以东有积极迹象。例如,TZ='Etc/GMT+4'使用缩写“GMT+4”,对应于UTC后4小时(即格林威治以西),尽管许多人认为这意味着UTC前4小时(即格林威治以东)


解析任意格式的最简单方法是使用一些正则表达式将其拆分为多个部分,然后以您可以使用的格式进行排列

const date='2017-11-28 23:37:52等/GMT';
常量[,年,月,日,小时,分钟,秒,时区]=日期.匹配(/(\d{4})-(\d{2})-(\d{2})-(\d{2}):(\d{2}):(\d{2})\sEtc\/([A-Z]{3})/;
日志(年、月、日、小时、分钟、秒、时区);
const parsedDate=新日期(`${year}-${month}-${day}${hour}:${minute}:${second}${timezone}`);

console.log(parsedDate)您可以采用以下两种策略之一:

  • 手动解析字符串并使用日期构造函数的部分,然后调整时区
  • 将时间戳转换为大多数正在使用的浏览器都应支持的字符串(即根据ECMA-262的ISO 8601扩展格式)
  • 第一种方法更健壮

    参考文献没有说明在Etc/格式中如何表示+0530这样的时区,因此以下内容不涉及这些时区:

    • “Etc/GMT”变为“+00:00”
    • “Etc/GMT+4”变为“-04:00”
    • “Etc/GMT-10”变为“+10:00”
    此外,以下函数不验证格式,它们假定提供的字符串是合适的

    //解析格式为2017-11-28 23:37:52 Etc/GMT的字符串
    函数parsePOZIX(s){
    var b=s.分割(“”);
    //这些是日期和时间部分
    var c=b[0]。拆分(/\D/).concat(b[1]。拆分(/\D/);
    //使用UTC创建新日期
    var d=新日期(Date.UTC(c[0],c[1]-1,c[2],c[3],c[4],c[5]);
    //现在调整时区
    var tz=b[2]。拆分('/')[1];
    变量符号=/^\+/.测试(tz)?1:-1;
    var hr=tz.替换(/\D/g',)||'0';
    d、 setUTCHours(d.getUTCHours()+符号*hr);
    返回d;
    }
    ['2017-11-28 23:37:52等/GMT',
    ‘2017-11-28 23:37:52等/+8’,
    ‘2017-11-28 23:37:52等/-10’】forEach(函数){
    console.log(s+'\n'+parsePOZIX(s.toISOString());
    
    });苹果返回的格式由ISO 8601日期时间和IANA时区组成。这是一种我在别处从未见过的奇怪格式,鉴于苹果的文档声称这是RFC3339日期时间字符串,这似乎是一个错误

    JavaScript对使用IANA时区没有内置支持。对于这一点,core Moment.js库也没有。然而,它确实如此。如果同时包含“时刻”和“时刻时区”库,则可以按如下方式解析日期:

    /**
     * Parse a datetime string returned from the Apple Receipt Validation Server, in
     * a format like:
     *     2017-11-28 23:37:52 Etc/GMT
     * and return its value as a Moment datetime object.
     */
    function parseAppleDatetime(appleDatetimeStr) {
        const [dateStr, timeStr, timezoneStr] = appleDatetimeStr.split(' '),
              datetimeStr = dateStr + ' ' + timeStr;
        return moment.tz(datetimeStr, timezoneStr);
    }
    
    现在,如果您这样做,例如:

    parseAppleDatetime('2017-11-28 23:37:52 Etc/GMT').format()
    
    。。。您将获得:

    "2017-11-28T23:37:52Z"
    

    看起来您的正则表达式正在删除
    Etc
    位。但我需要这个时区完全匹配。日期是RFC3339标准,如果我删除这些数据块,很可能会有时区错误。这是一种更标准的方法吗?这会导致非标准时间戳,因此解析会退回到特定于实现的启发式方法。因此结果是不可靠的:它在Safari中返回null,因为“GMT”时区无效。而且,我看不出它是如何处理“Etc/+8”这样的时区的。