最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why is moment.js diff method returning NaN? - Stack Overflow

programmeradmin2浏览0评论

Terminal output:

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

Code:

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

moment.js source:

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);
        }

Terminal output:

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

Code:

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

moment.js source:

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);
        }
Share Improve this question edited Aug 2, 2013 at 22:19 Matt Johnson-Pint 242k75 gold badges462 silver badges607 bronze badges asked Jan 13, 2013 at 6:46 user810606user810606 7
  • Are you using the latest moment.js? I'm using 1.7.2 and it's giving me back 59. – robertklep Commented Jan 13, 2013 at 7:02
  • Yes, I am using 1.7.2. I did moment(expDate._d) and it worked. Any idea why? – user810606 Commented Jan 13, 2013 at 7:12
  • Is expDate a real moment()-generated object? Or something you deserialized from JSON? – robertklep Commented Jan 13, 2013 at 7:15
  • 1 Yeah, it will be stored as a plain object in MongoDB, when you retrieve it you have to create a new moment object again (using moment(expDate._d), like you found out) before you can use it for calculations. – robertklep Commented Jan 13, 2013 at 7:22
  • 1 It depends, if those objects are instances of class-like objects with methods and such it'll give the same issues, MongoDB handles plain objects only so when retrieving those objects they return as plain JS objects. – robertklep Commented Jan 13, 2013 at 7:31
 |  Show 2 more comments

2 Answers 2

Reset to default 9

I had the same issue when comparing two moment objects. The problem I had was that the first moment was constructed specifying a UK date format while the second moment was created without specifying the UK date format and the date happened to have a day greater than 12 e.g 27th of the month. On closer inspection while debugging, the second date's moment object noted that its _d field was an invalid date.

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

The fix was to construct the second moment object and specify the date format.

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

From comments of the question, I gather that you are attempting to store a moment instance directly into MongoDB and then retrieve it later.

A moment isn't directly serializable, so this will always cause issues. You should instead obtain an ISO string from the moment:

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

Store that string in MongoDB. Later, when you retrieve it, you can construct a new moment instance from that value.

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

If you prefer something more compact, you could use the number obtained from m.valueOf() instead. But that's not as easy to read or manipulate.

Don't use the _d field suggested in comments. That is internal to moment, and shouldn't be used directly. It might not be what you are expecting.

发布评论

评论列表(0)

  1. 暂无评论