【问题标题】:Javascript: Difference between `new Date(dateString)` vs `new Date(year, month, day)`Javascript:`new Date(dateString)` 与`new Date(year, month, day)`之间的区别
【发布时间】:2014-09-16 09:21:47
【问题描述】:

参考此问题How do I get the number of days between two dates in JavaScript? 的已接受答案。我看到了,在函数parseDate

function parseDate(str) {
    var mdy = str.split('/')
    return new Date(mdy[2], mdy[0]-1, mdy[1]);
}

他正在这样做:

var mdy = str.split('/')
return new Date(mdy[2], mdy[0]-1, mdy[1]);

即将传递的日期拆分为月、日和年,然后将其传递给Date,例如new Date(year, month, day),而他可以简单地执行new Date(str),它会返回相同的结果(不是吗?)。谁能解释一下这两种方式的区别?

更新:测试结果:

var str = '1/1/2000'
var mdy = str.split('/')
console.log( new Date(str) ) // Sat Jan 01 2000 00:00:00 GMT+0500 (Pakistan Standard Time)
console.log( new Date(mdy[2], mdy[0]-1, mdy[1]) ); // Sat Jan 01 2000 00:00:00 GMT+0500 (Pakistan Standard Time)

【问题讨论】:

  • 不,它们不一样,即使假设你会在一个月后减去(他正在做mdy[0]-1),因为新的Date(str) 需要(按照标准)只接受日期特定格式(年/月/日,另请参见 this post),并且他们正在使用特定的语言环境规则进行解析(月/日/年)。老实说,我什至不会使用该代码进行解析(因为是的,实际上它会因不同的语言环境而被破坏)。
  • 根据您的更新:您使用的是 200 年 1 月 1 日,那么您不会看到差异,但浏览器必须仅接受(对于解析的日期)它在转换为字符串时产生的内容,并且它们 yyyy /mm/dd 格式。尝试 2014 年 1 月 1 日...这取决于语言环境(那么对于月份首先出现的语言环境,它将失败)。
  • @LearningNeverStops 是的,因为您的语言环境与他们通过手动解析所做的相匹配。例如,它会在我的语言环境(意大利语/意大利)中失败,因为我们写的是日/月/年(例如,“2014 年 12 月 21 日”是“21/12/2014”,但他们的解析例程需要“12/21 /2014" 并且转换显然会失败)。通常我总是强烈建议不要在 JavaScript 中手动进行日期解析,这是一个复杂的话题,并且有一些非常不错的库。

标签: javascript date


【解决方案1】:

不,它们不一样(即使假设您将在一个月后减去:他正在做 mdy[0] - 1)因为 new Date(str) 是必需的(按照标准,请参阅 §15.9.4.2 ) 仅接受特定格式 ISO 8601 的日期(YYYY-MM-DDTHH:mm:ss.sssZ,另请参阅 this post,我不会在这里重复自己):

如果字符串不符合该格式 [ISO 8601],则函数可能会退回到任何特定于实施的启发式或特定于实施的日期格式。

请注意(正如 Royi 在 comments 中指出的那样),也应该支持 RFC 2822 (根据 MDN),但 JavaScript specifications 中没有提到它,Internet Explorer 也没有t 正式支持它(见MSDN,它可以解析一些类似但不一样的东西)。

在该代码中,他们使用特定的语言环境规则进行解析(MM/DD/YYYY,我想en-US 语言环境,但它不仅仅是一个)。老实说,我什至不会使用该代码进行解析(因为是的,实际上它会因不同的语言环境而被破坏:即使用于分割的分隔符也不是“语言环境安全的”)。让我用一个例子来解释:

  • 您正在使用正确配置的日期时间选择器(或<input type="date"/>,如果支持),您将根据您的区域设置输入日期。例如在意大利(但一般在欧洲)我们写DD/MM/YYYY
  • 现在让我们假设用户选择了21 December 2014(根据他的语言环境格式化为21/12/2014)。
  • 使用字符串拆分该代码将失败(因为它会选择 21 作为月份编号,显然它是无效的)。更糟糕的是,此类错误甚至可能被忽视(例如,如果用户选择 1/2/2014 代码会“认为”它是 2nd Jan,但用户选择了 1st Feb)。你想让它更复杂吗?甚至 new Date(str) 也可能会失败,因为它依赖于浏览器(而且您不能真正相信 heuristic 具有便携性和安全性)。

如果您问自己“那他们为什么使用这样的代码?”我想说他们使用了一种快速解决方法来支持使用 en-US 语言环境的日期(可能是因为他们使用的浏览器不支持 启发式猜测),但这不是你应该重复使用的东西。

解决方案?永远不要手动解析日期(除非你真的很清楚你在做什么),为此使用一个好的库(例如moment.js),因为你可能对日期格式所做的大多数假设是......错了

【讨论】:

  • 接受特定格式 ISO 8601 的日期——不正确。它还将接受其他格式。它将首先尝试 iso,然后尝试启发式。另外:这种格式将始终产生本地结果(它不是iso)new Date("2013/07/27 10:10:10")
  • @RoyiNamir 严格来说很好(参见标准中引用的段落)需要解析 ISO 8601,它可能回退到 [... ]。这就是为什么我写了“必需”但我也发布了报价。该格式适用于 大多数 浏览器(AFAIK),但它不是标准的,并且不受所有旧浏览器的支持...
  • Also : dateString 表示 RFC2822ISO 8601 日期的字符串(可以使用其他格式,但结果可能是意外)。 所以它也可以处理 rfc 支持
  • @RoyiNamir 但 RFC2822 IE 不支持(我承认这并不奇怪):MSDN(参见 其他数据格式部分)和它在 JavaScript 规范中没有提及
【解决方案2】:

我尝试将您的测试代码输入到jsperf.com,我的机器上的结果很清楚,他们说您不应该尝试拆分字符串。

我使用拆分字符串尝试了两个测试,令人惊讶的是,拆分本身并不是占用时间的原因。

http://jsperf.com/date-from-string-or-dateparts自己尝试

【讨论】:

  • 这不是时间问题(一般我会选择更清晰简洁的,用户不会注意到这样的代码有任何区别)但是正确性......
猜你喜欢
  • 2017-02-14
  • 1970-01-01
  • 2019-11-12
  • 1970-01-01
  • 2020-03-12
  • 1970-01-01
  • 1970-01-01
  • 2021-04-09
相关资源
最近更新 更多