From: Iskren Chernev Date: Sun, 21 Jul 2013 08:29:30 +0000 (-0200) Subject: Added iso duration parsing #861 X-Git-Tag: 2.3.0~10^2~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9d8d61ed9d5fd37facf31b30f9efe6310c43bee;p=thirdparty%2Fmoment.git Added iso duration parsing #861 --- diff --git a/moment.js b/moment.js index c18547cbf..ad5e74fc9 100644 --- a/moment.js +++ b/moment.js @@ -22,6 +22,7 @@ // ASP.NET json date format regex aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)\:(\d+)\.?(\d{3})?/, + isoDurationRegex = /^P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, // format tokens formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g, @@ -1051,9 +1052,12 @@ var isDuration = moment.isDuration(input), isNumber = (typeof input === 'number'), duration = (isDuration ? input._input : (isNumber ? {} : input)), - matched = aspNetTimeSpanJsonRegex.exec(input), + // matching against regexp is expensive, do it on demand + aspMatched = null, + isoMatched = null, sign, - ret; + ret, + parseIso; if (isNumber) { if (key) { @@ -1061,15 +1065,31 @@ } else { duration.milliseconds = input; } - } else if (matched) { - sign = (matched[1] === "-") ? -1 : 1; + } else if (!!(aspMatched = aspNetTimeSpanJsonRegex.exec(input))) { + sign = (aspMatched[1] === "-") ? -1 : 1; duration = { y: 0, - d: ~~matched[2] * sign, - h: ~~matched[3] * sign, - m: ~~matched[4] * sign, - s: ~~matched[5] * sign, - ms: ~~matched[6] * sign + d: ~~aspMatched[2] * sign, + h: ~~aspMatched[3] * sign, + m: ~~aspMatched[4] * sign, + s: ~~aspMatched[5] * sign, + ms: ~~aspMatched[6] * sign + }; + } else if (!!(isoMatched = isoDurationRegex.exec(input))) { + parseIso = function (inp) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + return isNaN(res) ? 0 : res; + }; + duration = { + y: parseIso(isoMatched[1]), + M: parseIso(isoMatched[2]), + d: parseIso(isoMatched[3]) + parseIso(isoMatched[7]) * 7, + h: parseIso(isoMatched[4]), + m: parseIso(isoMatched[5]), + s: parseIso(isoMatched[6]), }; } diff --git a/test/moment/duration.js b/test/moment/duration.js index 29feb9269..29cfbf557 100644 --- a/test/moment/duration.js +++ b/test/moment/duration.js @@ -198,6 +198,17 @@ exports.duration = { test.done(); }, + "instatiation from iso 8601 duration" : function (test) { + test.expect(6); + test.equal(moment.duration('P1Y2M3DT4H5M6S').asSeconds(), moment.duration({y: 1, M: 2, d: 3, h: 4, m: 5, s: 6}).asSeconds(), "all fields"); + test.equal(moment.duration('P1W').asSeconds(), moment.duration({d: 7}).asSeconds(), "week field"); + test.equal(moment.duration('P1M').asSeconds(), moment.duration({M: 1}).asSeconds(), "single month field"); + test.equal(moment.duration('PT1M').asSeconds(), moment.duration({m: 1}).asSeconds(), "single minute field"); + test.equal(moment.duration('P1MT2H').asSeconds(), moment.duration({M: 1, h: 2}).asSeconds(), "random fields missing"); + test.equal(moment.duration('PY1MDT2HMS').asSeconds(), moment.duration({M: 1, h: 2}).asSeconds(), "random values missing"); + test.done(); + }, + "humanize" : function (test) { test.expect(32); moment.lang('en');