【问题标题】:Why is moment.js diff method returning NaN?为什么 moment.js diff 方法返回 NaN?
【发布时间】:2012-12-27 09:38:45
【问题描述】:

终端输出:

Now:  { _d: Sat Jan 13 2018 02:39:25 GMT-0400 (AST),
      _isUTC: false,
      _a: null,
      _lang: false }
Expiration Date: { _d: Wed Feb 13 2013 02:00:15 GMT-0400 (AST),
      _isUTC: false,
      _a: null,
      _lang: false }
Difference between Now and Expiration Date: NaN

代码:

console.log('Difference between Now and Expiration Date:', now.diff(expDate, 'months', true));

moment.js 来源:

diff : function (input, val, asFloat) {
            var inputMoment = this._isUTC ? moment(input).utc() : moment(input).local(),
                zoneDiff = (this.zone() - inputMoment.zone()) * 6e4,
                diff = this._d - inputMoment._d - zoneDiff,
                year = this.year() - inputMoment.year(),
                month = this.month() - inputMoment.month(),
                date = this.date() - inputMoment.date(),
                output;
            if (val === 'months') {
                output = year * 12 + month + date / 30;
            } else if (val === 'years') {
                output = year + (month + date / 30) / 12;
            } else {
                output = val === 'seconds' ? diff / 1e3 : // 1000
                    val === 'minutes' ? diff / 6e4 : // 1000 * 60
                    val === 'hours' ? diff / 36e5 : // 1000 * 60 * 60
                    val === 'days' ? diff / 864e5 : // 1000 * 60 * 60 * 24
                    val === 'weeks' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
                    diff;
            }
            return asFloat ? output : round(output);
        }

【问题讨论】:

  • 你使用的是最新的 moment.js 吗?我正在使用 1.7.2,它让我返回 59
  • 是的,我使用的是 1.7.2。我做了moment(expDate._d),它奏效了。知道为什么吗?
  • expDate 是真实的 moment() 生成的对象吗?或者你从 JSON 反序列化的东西?
  • 是的,它将作为普通对象存储在 MongoDB 中,当您检索它时,您必须再次创建一个新的时刻对象(使用 moment(expDate._d),就像您发现的那样)才能使用它用于计算。
  • 这取决于,如果这些对象是具有方法的类对象的实例,并且会产生相同的问题,MongoDB 只处理普通对象,因此在检索这些对象时,它们将作为普通 JS 对象返回。

标签: javascript mongodb serialization momentjs


【解决方案1】:

根据问题的 cmets,我了解到您正试图将 moment 实例直接存储到 MongoDB 中,然后再检索它。

moment 不能直接序列化,所以这总是会导致问题。您应该从现在开始获取 ISO 字符串:

var m = moment();
var s = m.toISOString(); //  "2013-08-02T20:13:45.123Z"

将该字符串存储在 MongoDB 中。稍后,当您检索它时,您可以从该值构造一个新的时刻实例。

var m = moment("2013-08-02T20:13:45.123Z");

如果你喜欢更紧凑的东西,你可以使用从m.valueOf() 获得的数字。但这并不容易阅读或操作。

不要使用 cmets 中建议的 _d 字段。那是时刻内部的,不应该直接使用。这可能不是您所期望的。

【讨论】:

  • 谢谢! @matt-johnson ISO 字符串对我有用。在 cordova/phonegap SDK 上使用 moment() diff() 时出现问题,其中时间戳数据来自 JSON/Database。
  • @whitedeath - 不确定你的意思,但你确实可以使用其他格式。你只需要specify the format
  • 不用担心我的评论可能对其他人有所帮助,因为它在我的上下文中有所帮助(移动混合 - cordova/phonegap SDK 项目 - 其中数据时间戳来自 JSON/数据库响应它在转换时返回 NaN the moment() - 如果它被存储,你的 ISO 字符串会修复它)。
【解决方案2】:

比较两个矩对象时,我遇到了同样的问题。我遇到的问题是,第一个时刻是在指定英国日期格式的情况下构建的,而第二个时刻是在没有指定英国日期格式的情况下创建的,并且日期恰好有一天大于 12,例如本月 27 日。在调试时仔细检查,第二个日期的时刻对象指出其 _d 字段是无效日期。

var startDate = moment("23/09/2019", "DD/MM/YYYY");
var endDate = moment("27/09/2019");
var dateDiff = startDate.diff(endDate, "days"); // returns NaN

修复方法是构造第二个矩对象并指定日期格式。

var endDate = moment("27/09/2019", "DD/MM/YYYY");

【讨论】:

    猜你喜欢
    • 2017-05-10
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 2015-05-20
    • 2021-06-25
    • 2020-01-07
    • 2011-10-23
    相关资源
    最近更新 更多