From e8d00a08868f46080d9967c03a641ea7a435645d Mon Sep 17 00:00:00 2001 From: scommisso Date: Thu, 8 Sep 2016 14:09:21 -0700 Subject: [PATCH] Add support for weeks and multiple units --- index.js | 67 ++++++++++++++++++++++++++++++++++++++++++++++++--- package.json | 3 +++ test/index.js | 24 ++++++++++++++++-- 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 9f1fd26..684c890 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,9 @@ var s = 1000; var m = s * 60; var h = m * 60; var d = h * 24; +var w = d * 7; var y = d * 365.25; +var separators = [' ', '.', ',']; /** * Parse or format the given `val`. @@ -23,14 +25,14 @@ var y = d * 365.25; module.exports = function(val, options){ options = options || {}; - if ('string' == typeof val) return parse(val); + if ('string' === typeof val) return parse(val); return options['long'] ? fmtLong(val) : fmtShort(val); }; /** - * Parse the given `str` and return milliseconds. + * Parse the given `str` and return milliseconds. Can contain multiple units. * * @param {String} str * @return {Number} @@ -38,9 +40,64 @@ module.exports = function(val, options){ */ function parse(str) { + var units = tokenize(str); + if (!units.length) { return; } + + var ms = 0; + var parsed, i; + for (i = 0; i < units.length; i++) { + parsed = parseString(units[i]); + if ('undefined' === typeof parsed) { return; } + ms += parsed; + } + return ms; +} + +/** + * Splits the given `str` into multiple unit/value tokens. + * + * @param {String} str + * @return {Array} + * @api private + */ + +function tokenize(str) { + var units = []; + var buf = ''; + var sawLetter = false; + var i, c; + for (i = 0; i < str.length; i++) { + c = str[i]; + if (~separators.indexOf(c)) { + buf += c; + } else if (isNaN(c)) { + sawLetter = true; + buf += c; + } else { + if (sawLetter) { + units.push(buf.trim()); + buf = ''; + } + sawLetter = false; + buf += c; + } + } + if (buf.length) { units.push(buf.trim()); } + return units; +} + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parseString(str) { str = '' + str; if (str.length > 10000) return; - var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str); + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str); if (!match) return; var n = parseFloat(match[1]); var type = (match[2] || 'ms').toLowerCase(); @@ -51,6 +108,10 @@ function parse(str) { case 'yr': case 'y': return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; case 'days': case 'day': case 'd': diff --git a/package.json b/package.json index 0009150..c36d07e 100644 --- a/package.json +++ b/package.json @@ -21,5 +21,8 @@ "scripts": { "ms/index.js": "index.js" } + }, + "scripts": { + "test": "./node_modules/mocha/bin/_mocha ./test/* -R spec" } } diff --git a/test/index.js b/test/index.js index d7aa8d1..0384d92 100644 --- a/test/index.js +++ b/test/index.js @@ -19,14 +19,18 @@ describe('ms(string)', function(){ expect(ms('1m')).to.be(60000); }); - it('should convert from h to ms', function () { - expect(ms('1h')).to.be(3600000); + it('should convert w to ms', function () { + expect(ms('2w')).to.be(1209600000); }); it('should convert d to ms', function () { expect(ms('2d')).to.be(172800000); }); + it('should convert from h to ms', function () { + expect(ms('1h')).to.be(3600000); + }); + it('should convert s to ms', function () { expect(ms('1s')).to.be(1000); }); @@ -43,6 +47,14 @@ describe('ms(string)', function(){ expect(ms('1 s')).to.be(1000); }); + it('should work with multiple units', function () { + expect(ms('1h1m32s')).to.be(3692000); + }); + + it('should work with multiple units with spaces', function () { + expect(ms('1 h 1 m 32 s')).to.be(3692000); + }); + it('should return NaN if invalid', function () { expect(isNaN(ms('☃'))).to.be(true); }); @@ -83,9 +95,17 @@ describe('ms(long string)', function(){ expect(ms('2 days')).to.be(172800000); }); + it('should convert weeks to ms', function () { + expect(ms('2 weeks')).to.be(1209600000); + }); + it('should work with decimals', function () { expect(ms('1.5 hours')).to.be(5400000); }); + + it('should work with multiple units', function () { + expect(ms('1 hour 1 minute 32 seconds')).to.be(3692000); + }); }) // numbers