Firefox和其他浏览器之间的JavaScript日期问题

5

有人知道为什么在Firefox中执行以下代码,如果传入的字符串是四个数字且仅为四个数字,则它将将其验证为日期吗?在我测试的所有其他浏览器(IE,Chrome)中,它始终返回不是日期。

由于规范,如Marcel Korpel所指出的那样,指出它应该回退到使用Firefox的特定于实现的回退,因此我真的想知道为什么Firefox的回退会显示这种异常情况。

function isDate(sDate) {  
    var temp = new Date(sDate);  
    if (temp.toString() == "NaN" || temp.toString() == "Invalid Date") {  
        alert("Not a Date");  
    } else {  
        alert("Is a Date!");  
    }
}

请使用4个空格缩进您的代码,不要像您所做的那样使用反引号。 - Marcel Korpel
在一个分支中返回true,在另一个分支中不返回任何东西... ???!? - Jason S
是的,我试着写一个快速而简单的isDate函数,却忘了加入“返回false”的语句。让我在这个讨论中删掉“返回true”的语句。 - Brian S.
为什么要使用 toString 来测试 NaN?而不是使用 isNaN(temp) - Marcel Korpel
4个回答

5
如果您将字符串传递给Date构造函数,则该字符串应采用parse方法(IETF兼容RFC 1123时间戳)所识别的格式(来源:MDC)。其他任何内容都会导致实现特定行为,并且在各种浏览器中会有所不同。
我建议您根本不要使用字符串,而是使用表示年份、月份和日期的三个数字(请注意,月份从0开始(=一月)),或者使用一个数字,即自1970年1月1日00:00:00 UTC以来的毫秒数。 更新:看到您的示例,
var a = new Date('0123');
console.log(a);

输出

Fri Jan 01 0123 01:00:00 GMT+0100 (CET)

火狐显然将'0123'识别为年份。

更新2:我认为MDC对Date.parse的描述包含了你的问题的答案:

从JavaScript 1.8.5开始,还可以解析ISO 8601格式的日期字符串的子集。


ISO 8601页面指定(“格式”部分):

年:
YYYY(例如1997)
年和月:
YYYY-MM(例如1997-07)
完整日期:
YYYY-MM-DD(例如1997-07-16)


因此,当依赖于ISO 8601时,仅包含四个数字的字符串将被识别为年份。

我知道这不符合规范,只是想知道为什么Firefox会显示这种行为。 - Brian S.
1
@Brian:这只是因为它的行为没有被指定;根据ECMAScript规范,“[如果字符串不符合该格式,则函数可能会回退到任何特定于实现的启发式或特定于实现的日期格式]”。如果字符串无法识别为日期,则Date构造函数返回NaN。只是有些浏览器比其他浏览器更宽容。 - Marcel Korpel
我想我真正想问的是为什么Firefox的特定于实现的回退会将'123'的返回值设置为NaN而将'0123'的返回值设置为日期。 我应该编辑我的帖子以更好地说明我的问题吗? - Brian S.
这还更奇怪了。因此,出于某些原因,Firefox 将“0000”作为有效年份接受?这可能是一个 bug 吗? - Brian S.
1
啊,现在我明白了。当传入一个字符串时,Firefox 会尝试对其进行 date.parse 操作,而 '1234' 恰好可以工作,而 '123' 则不行。谢谢! - Brian S.

1
不要依赖 JavaScript 中的日期验证。本地日期时间格式可能会对 JavaScript 日期对象造成一些问题。
请使用以下方法:
  • 显示不可编辑文本框
  • 当文本框聚焦时,显示日历
  • 进行空值验证,如果该字段必须填写
  • 无需执行日期验证,因为如果文本框的值不为空,那么它肯定是日期。我们不允许用户输入其他内容,并且从日历选择的值始终是日期 :)

1
这在所有浏览器中都有效 -

new Date('2001/01/31 12:00:00 AM')


你刚刚告诉了我为什么当我在对象上应用新的Date()对象创建时它失败了。Firefox在传递破折号“-”时会失败,而Chrome则不会。将其替换为斜杠“/”就解决了问题。 - neoswf

0

我在Firefox中遇到了与此相同的问题,出于某些我无法解释的原因,在FF中任何4位数字字符都是有效日期,在其他浏览器中则为NaN:

对于FF来说有点恶心的解决方法,但这对我起作用了:

function isDate(sDate) {  
    if(sDate.match(/^\d{4}$/))
       return false;
    var temp = new Date(sDate);  
    if (temp.toString() == "NaN" || temp.toString() == "Invalid Date") {  
        alert("Not a Date");  
    } else {  
        alert("Is a Date!");  
        return true;  
    }
}

谢谢你的解决方法!我想我也会在我的代码中使用类似的东西。 - Brian S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接