From 77f5da635c58538b1d98299474137ae48eec48df Mon Sep 17 00:00:00 2001 From: Kunal Marwaha Date: Fri, 20 Jan 2017 21:23:29 -0500 Subject: [PATCH] Add validity check for decimal values on non-smallest duration unit --- src/lib/duration/valid.js | 17 ++++++++++++++++- src/test/moment/duration.js | 4 ++-- src/test/moment/duration_invalid.js | 12 ++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/lib/duration/valid.js b/src/lib/duration/valid.js index 799100c86..ebb8fcaf6 100644 --- a/src/lib/duration/valid.js +++ b/src/lib/duration/valid.js @@ -1,9 +1,24 @@ +var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond']; + export default function isDurationValid(m) { for (var key in m) { - if (['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'].indexOf(key) === -1 || + if (ordering.indexOf(key) === -1 || m[key] !== undefined && isNaN(parseInt(m[key]))) { return false; } } + + var unitHasDecimal = false; + for (var i = 0; i < ordering.length; ++i) { + if (m[ordering[i]]) { + if (unitHasDecimal) { + return false; // only allow non-integers for smallest unit + } + if (parseFloat(m[ordering[i]]) !== parseInt(m[ordering[i]])) { + unitHasDecimal = true; + } + } + } + return true; } diff --git a/src/test/moment/duration.js b/src/test/moment/duration.js index dc57f21ca..c7e0ea377 100644 --- a/src/test/moment/duration.js +++ b/src/test/moment/duration.js @@ -305,7 +305,7 @@ test('serialization to ISO 8601 duration strings', function (assert) { assert.equal(moment.duration({M: -1}).toISOString(), '-P1M', 'one month ago'); assert.equal(moment.duration({m: -1}).toISOString(), '-PT1M', 'one minute ago'); assert.equal(moment.duration({s: -0.5}).toISOString(), '-PT0.5S', 'one half second ago'); - assert.equal(moment.duration({y: -0.5, M: 1}).toISOString(), '-P5M', 'a month after half a year ago'); + assert.equal(moment.duration({y: -1, M: 1}).toISOString(), '-P11M', 'a month after a year ago'); assert.equal(moment.duration({}).toISOString(), 'P0D', 'zero duration'); assert.equal(moment.duration({M: 16, d:40, s: 86465}).toISOString(), 'P1Y4M40DT24H1M5S', 'all fields'); }); @@ -315,7 +315,7 @@ test('toString acts as toISOString', function (assert) { assert.equal(moment.duration({M: -1}).toString(), '-P1M', 'one month ago'); assert.equal(moment.duration({m: -1}).toString(), '-PT1M', 'one minute ago'); assert.equal(moment.duration({s: -0.5}).toString(), '-PT0.5S', 'one half second ago'); - assert.equal(moment.duration({y: -0.5, M: 1}).toString(), '-P5M', 'a month after half a year ago'); + assert.equal(moment.duration({y: -1, M: 1}).toString(), '-P11M', 'a month after a year ago'); assert.equal(moment.duration({}).toString(), 'P0D', 'zero duration'); assert.equal(moment.duration({M: 16, d:40, s: 86465}).toString(), 'P1Y4M40DT24H1M5S', 'all fields'); }); diff --git a/src/test/moment/duration_invalid.js b/src/test/moment/duration_invalid.js index c56662191..e888310a5 100644 --- a/src/test/moment/duration_invalid.js +++ b/src/test/moment/duration_invalid.js @@ -9,6 +9,18 @@ test('invalid duration', function (assert) { assert.ok(isNaN(m.valueOf())); }); +test('invalid duration - only smallest unit can have decimal', function (assert) { + var m = moment.duration({'days': 3.5, 'hours': 1.1}); // should be invalid + assert.equal(m.isValid(), false); + assert.ok(isNaN(m.valueOf())); // .valueOf() returns NaN for invalid durations +}); + +test('valid duration - smallest unit can have decimal', function (assert) { + var m = moment.duration({'days': 3, 'hours': 1.1}); // should be valid + assert.equal(m.isValid(), true); + assert.equal(m.asHours(), 73.1); +}); + test('invalid duration with two arguments', function (assert) { var m = moment.duration(NaN, 'days'); assert.equal(m.isValid(), false); -- 2.47.2