Moment: isSameOrAfter 在比较 moment() 和 moment() 时给出随机输出

创建于 2017-02-21  ·  4评论  ·  资料来源: moment/moment

描述
所以,我和一位同事在我们的代码中发现了一个错误,结果证明是我们使用了未定义的变量(基本上是moment(undefined) ,然后尝试将其与新的矩实例( moment() ) 与方法isSameOrAfter

所以我们基本上使用的是:

let isSame = moment(undefined).isSameOrAfter(moment());

运行该代码一两次会返回true ,但并非总是如此。 偶尔它会返回false ,我想这是因为创建两个时刻的实例,一个接一个,没有定义时间可能会创建它们有几微秒的差异。

这是我在 Windows 10 上的 Node v7.1.0 和使用 Moment.js 2.17.1 的 Chrome/56.0.2924.87 中运行的测试。

const moment = require('moment');

function isSameOrAfter() {
    console.log('isSameOrAfter')
    for (let i = 0; i < 1000; i++) {
        let output = moment().isSameOrAfter(moment());
        if (!output) {
            console.log(output, i);
        }
    }
}

function isSame() {
    console.log('isSame')
    for (let i = 0; i < 1000; i++) {
        let output = moment().isSame(moment());
        if (!output) {
            console.log(output, i);
        }
    }
}

function sameExactVariable() {
    console.log('Another test comparing the same exact variable')
    for (let i = 0; i < 1000; i++) {
        const now = moment();
        let output = now.isSame(now);
        if (!output) {
            console.log(output, i);
        }
    }
}

isSameOrAfter();
isSame();
sameExactVariable();

前两个函数会在 1000 次中记录false几次,而第三个函数则不会。 它仅在遇到异常时记录。

环境:
2017 年 2 月 21 日星期二 14:36:06 GMT+0100(西欧标准时间)
2017-02-21 14:36:06
-60
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
2.17.1

最有用的评论

@imrvshah首先请注意

...isSameOrAfter(moment().format('MM-DD-YYYY'))

使用当前时间创建一个新时刻,将其格式化为字符串,然后将该字符串传递给isSameOrAfter() ,后者再次对其进行解析。 你应该刚刚说:

...isSameOrAfter(moment())

并保存了时刻-> 字符串-> 时刻工作。 这是更好的代码,但我也打赌它修复了错误。 您是否注意到弃用警告说“嘿,您不应该像那样将字符串传递给时刻”? Moment 知道如何解析 ISO 8601 字符串,如moment("1982-05-25") 。 它还知道如何解析指定格式的字符串,例如moment("05-25-1982", "MM-DD-YYYY") 。 但是它不知道像“05-25-1982”这样的字符串是“MM-DD-YYYY”而没有你告诉它。 所以它让浏览器通过将该字符串传递给Date构造函数来猜测。 换句话说,你的代码是这样展开的:

m.isSameOrAfter("05-25-1982");
m.isSameOrAfter(moment("05-25-1982"))
m.isSameOrAfter(moment(new Date("05-25-1982")))

我们不赞成这样做是有原因的:它会根据运行它的浏览器提供不一致的结果。 所以你遇到的是iOS本身不支持这种格式。 在我的 Safari 开发控制台中:

> new Date("05-25-1982")
Invalid Date

这给了你不好的比较,给你留下了一个空数组。

所有4条评论

可能我也有同样的问题。 它在 chrome 和 Android 设备上按预期工作,但在 iOS 上没有。

let arrDates: Array<String> = []; _.each(Dates, (date) => { if (moment(date).isSameOrAfter(moment().format('MM-DD-YYYY'))) { arrDates.push(date); } });

在 iOS 中,当它在 chrome 和 Android 上工作时,我得到数组 null。

环境:

科尔多瓦 CLI:6.4.0
离子框架版本:2.0.0
离子 CLI 版本:2.1.18
离子应用程序库版本:2.1.9
离子应用脚本版本:1.0.0
ios-部署版本:1.9.0
ios-sim 版本:5.0.13
操作系统:macOS Sierra
节点版本:v6.9.2
Xcode 版本:Xcode 8.2.1 构建版本 8C1002

@ErikMartensson

我想这是因为在彼此之后创建两个时刻实例,没有定义时间可能会创建它们有几微秒的差异。

是的, moment()moment(undefined) ——它们是相同的 —— 意味着现在。 JS 日期具有毫秒分辨率,因此如果现在是不同的毫秒(有时会发生这种情况),则一次又一次。 AFAIK,JS 没有定义moment().isSameOrAfter(moment())评估这两个moment()调用的顺序。 但是因为它显然必须在执行isSameOrAfter()之前进行第二次调用,所以如果实践中的第二次调用总是首先出现,我不会感到惊讶。 这意味着如果存在时差,它也会使测试的“orAfter”部分失败。 您可以使用调试器确认这一点。

我不知道该告诉你什么。 这就是有限分辨率日期时间的工作方式; “现在”是指不同的时间,取决于你说它的时间。

@imrvshah首先请注意

...isSameOrAfter(moment().format('MM-DD-YYYY'))

使用当前时间创建一个新时刻,将其格式化为字符串,然后将该字符串传递给isSameOrAfter() ,后者再次对其进行解析。 你应该刚刚说:

...isSameOrAfter(moment())

并保存了时刻-> 字符串-> 时刻工作。 这是更好的代码,但我也打赌它修复了错误。 您是否注意到弃用警告说“嘿,您不应该像那样将字符串传递给时刻”? Moment 知道如何解析 ISO 8601 字符串,如moment("1982-05-25") 。 它还知道如何解析指定格式的字符串,例如moment("05-25-1982", "MM-DD-YYYY") 。 但是它不知道像“05-25-1982”这样的字符串是“MM-DD-YYYY”而没有你告诉它。 所以它让浏览器通过将该字符串传递给Date构造函数来猜测。 换句话说,你的代码是这样展开的:

m.isSameOrAfter("05-25-1982");
m.isSameOrAfter(moment("05-25-1982"))
m.isSameOrAfter(moment(new Date("05-25-1982")))

我们不赞成这样做是有原因的:它会根据运行它的浏览器提供不一致的结果。 所以你遇到的是iOS本身不支持这种格式。 在我的 Safari 开发控制台中:

> new Date("05-25-1982")
Invalid Date

这给了你不好的比较,给你留下了一个空数组。

@坎布隆

我同意你的看法,并在控制台中找出案例,由于日期格式,它是弃用警告。

感谢您关于不要多次包装它而只是使用的评论。 ...isSameOrAfter(moment())

此页面是否有帮助?
0 / 5 - 0 等级