是否有任何破解v8日期解析器的解决方法?

Vla*_*kov 19 javascript datetime v8 date node.js

V8日期解析器坏了:

> new Date('asd qw 101')
Sat Jan 01 101 00:00:00 GMT+0100 (CET)
Run Code Online (Sandbox Code Playgroud)

我可以像这样使用脆弱的正则表达式:

\d{1,2} (jan|feb|mar|may|jun|jul|aug|sep|oct|nov|dec) \d{1,4}
Run Code Online (Sandbox Code Playgroud)

但它太脆弱了.我不能依赖new Date (在V8中发布)并且也无法帮助我,因为时刻正在摆脱日期检测(github issue-thread).

是否有任何破解v8日期解析器的解决方法?

要清楚.我们有Gecko和V8都有Date.V8破坏了日期,Gecko已经工作了.我需要DateGecko中的from(Firefox).

更新:它肯定是破解了解析器https://code.google.com/p/v8/issues/detail?id=2602
不, Status: WorkingAsIntended

nal*_*inc 27

Date 对象基于时间值,即自UTC时间1970年1月1日以来的毫秒数,并具有以下构造函数

new Date();
new Date(value);
new Date(dateString);
new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);
Run Code Online (Sandbox Code Playgroud)

文档中,

dateString in new Date(dateString)是表示日期的字符串值.该字符串应该是在格式识别Date.parse()方法(IETF兼容RFC 2822的时间戳,并且还一个版本的ISO8601).

现在看一下date.js 中的v8源代码:

function DateConstructor(year, month, date, hours, minutes, seconds, ms) {
  if (!%_IsConstructCall()) {
    // ECMA 262 - 15.9.2
    return (new $Date()).toString();
  }

  // ECMA 262 - 15.9.3
  var argc = %_ArgumentsLength();
  var value;
  if (argc == 0) {
    value = %DateCurrentTime();
    SET_UTC_DATE_VALUE(this, value);
  } else if (argc == 1) {
    if (IS_NUMBER(year)) {
      value = year;
    } else if (IS_STRING(year)) {
      // Probe the Date cache. If we already have a time value for the
      // given time, we re-use that instead of parsing the string again.
      var cache = Date_cache;
      if (cache.string === year) {
        value = cache.time;
      } else {
        value = DateParse(year);               <- DOES NOT RETURN NaN
        if (!NUMBER_IS_NAN(value)) {
          cache.time = value;
          cache.string = year;
        }
      }

    }
...
Run Code Online (Sandbox Code Playgroud)

它看起来像是DateParse()没有为一个字符串返回NaN 'asd qw 101',因此错误.您可以Date.parse('asd qw 101')Chrome(v8) [返回-58979943000000]和Gecko(Firefox) [返回NaN]中交叉检查相同内容.Sat Jan 01 101 00:00:00当您new Date()使用时间戳-58979943000000(在两个浏览器中)播种时

是否有任何破解v8日期解析器的解决方法?

我不会说V8日期解析器坏了.它只是尝试满足对字符串RFC 2822标准在尽可能最好的方式但这样做的壁虎和两个休息 给出不同的结果,在某些情况下.

尝试 new Date('Sun Ma 10 2015') 使用Chrome(V8)和Firefox(Gecko)来解决另一个异常现象. Chrome无法确定天气'Ma'代表'March'或'May'并且在Firefox没有时给出无效日期.

解决方法:

您可以创建自己的包装器Date()来过滤V8自己的解析器不能的那些字符串.但是,在ECMA-5中对内置函数进行子类化是不可行的.在ECMA-6中,可以对内置构造函数(Array,Date和Error)进行子类化 - 引用

但是,您可以使用更强大的正则表达式来验证RFC 2822/ISO 8601的字符串

^(?:(?:31(\/|-|\. |\s)(?:0?[13578]|1[02]|(?:Jan|Mar|May|Jul|Aug|Oct|Dec)))\1|(?:(?:29|30)(\/|-|\.|\s)(?:0?[1,3-9]|1[0-2]|(?:Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.|\s)(?:0?2|(?:Feb))\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.|\s)(?:(?:0?[1-9]|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep))|(?:1[0-2]|(?:Oct|Nov|Dec)))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$
Run Code Online (Sandbox Code Playgroud)

图片正则表达式debuggex生成的图像

所以,看起来v8打破了它,它的工作方式不同.

希望能帮助到你!

  • 它有很大帮助.顺便说一句,今天我发现从2013年3月开始的一个问题是V8解析器应该返回"NaN"顺便说一下我仍然觉得它破了https://code.google.com/p/v8/issues/detail?id=2602,所以很可能是正式破产 (2认同)
  • 或者可能不是"状态:WorkingAsIntended" (2认同)

Mat*_*int 11

您似乎要求一种方法来解析可能采用任何特定格式的字符串并确定表示哪些数据.一般来说,这是一个坏主意的原因有很多.

你说moment.js是"摆脱日期检测",但实际上它从来没有这个功能.人们只是假设它可以做到这一点,并且在某些情况下它起作用,并且在许多情况下它没有.

这是一个说明问题的例子.

 var s = "01.02.03";
Run Code Online (Sandbox Code Playgroud)

这是约会吗?也许.也许不吧.它可以是文档中的部分标题.即使我们说这是一个约会,它的日期是什么时候?它可以解释为以下任何一种:

  • 2003年1月2日
  • 1月2日,0003
  • 2003年2月1日
  • 2月1日,0003
  • 2001年2月3日
  • 0001年2月3日

消除歧义的唯一方法是了解当前的文化日期设置.Javascript的Date对象就是这样 - 这意味着您将获得不同的值,具体取决于运行代码的计算机的设置.但是,moment.js是关于所有环境的稳定性.文化设置是明确的,通过时刻自己的区域设置功能.依赖浏览器的文化设置会导致解释错误.

最好的办法是明确你正在使用的格式.不允许随机垃圾输入.期望您以特定格式输入,并使用正则表达式提前验证该格式,而不是仅仅尝试构建Date并查看它是否在事后有效.

如果你不能这样做,你将不得不找到其他背景来帮助决定.例如,如果您从后端进程中抓取Web的一些随机位,并且您想从文本中提取日期,则必须了解每个特定网页的语言和区域设置.你可能猜到了,但是你可能错了很多时间.

另见:垃圾进,垃圾出


std*_*b-- 10

ES5 15.9.4.2 Date.parse: /.../如果String不符合该格式,则该函数可以回退到任何特定于实现的启发式或特定于实现的日期格式.无法识别字符串或包含格式为String的非法元素值的日期将导致Date.parse返回NaN.

所以没关系,根据上面引用的v8 date解析器的结果:

  1. new Date('asd qw 101') :1月01日101:00 00:00:00 GMT + 0100(CET)
  2. new Date('asd qw') : 失效日期

  • @VladimirStarkov Becaus`任何特定于实现的启发式或特定于实现的日期格式 (2认同)