diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d993c61 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.10" + - "0.11" +after_script: + - npm run coveralls diff --git a/README.md b/README.md new file mode 100644 index 0000000..6bbd873 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# moment-precise-range + +[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coveralls Status][coveralls-image]][coveralls-url] [![Dependencies][dependencies-image]][dependencies-url] + +A moment.js plugin to display human readable date/time ranges with precision. + +## Installation + +``` +npm install moment-precise-range --save +``` + +## Usage + +``` +// Will be the moment return by the moment module, with preciseDiff appended +var moment = require('moment-precise-rage'); + +var result = moment.preciseDiff(moment('2013-10-21 10:15:40', 'YYYY-MM-DD HH:mm:ss'), + moment('2014-02-02 01:01:01', 'YYYY-MM-DD HH:mm:ss')); + +console.log(result); // 3 months 11 days 14 hours 45 minutes a few seconds +``` + +[npm-url]: https://npmjs.org/package/moment-precise-range +[npm-image]: http://img.shields.io/npm/v/moment-precise-range.svg + +[travis-url]: https://travis-ci.org/mtscout6/moment-precise-range +[travis-image]: https://travis-ci.org/mtscout6/moment-precise-range.svg?branch=master + +[coveralls-url]: https://coveralls.io/r/mtscout6/moment-precise-range +[coveralls-image]: https://img.shields.io/coveralls/mtscout6/moment-precise-range.svg?branch=master + +[dependencies-url]: https://www.versioneye.com/user/projects/53e3f13ce0a229f1b7000057 +[dependencies-image]: https://www.versioneye.com/user/projects/53e3f13ce0a229f1b7000057/badge.svg diff --git a/coverage/coverage.json b/coverage/coverage.json new file mode 100644 index 0000000..1050301 --- /dev/null +++ b/coverage/coverage.json @@ -0,0 +1 @@ +{"/Users/smithm/dev/moment-precise-range/index.js":{"path":"/Users/smithm/dev/moment-precise-range/index.js","s":{"1":1,"2":1,"3":0,"4":1,"5":44,"6":44,"7":44,"8":1,"9":43,"10":1,"11":1,"12":1,"13":43,"14":43,"15":43,"16":43,"17":43,"18":43,"19":43,"20":13,"21":13,"22":43,"23":5,"24":5,"25":43,"26":12,"27":12,"28":43,"29":25,"30":25,"31":4,"32":21,"33":25,"34":43,"35":14,"36":14,"37":43,"38":43,"39":43,"40":43,"41":43,"42":43,"43":43,"44":43,"45":9,"46":43,"47":24,"48":43,"49":23,"50":43,"51":11,"52":43,"53":11,"54":43,"55":12,"56":43,"57":1},"b":{"1":[44,38],"2":[1,43],"3":[1,42],"4":[13,30],"5":[5,38],"6":[12,31],"7":[25,18],"8":[4,21],"9":[14,29],"10":[9,34],"11":[43,9],"12":[24,19],"13":[43,25],"14":[23,20],"15":[43,25],"16":[11,32],"17":[43,14],"18":[11,32],"19":[43,15],"20":[12,31],"21":[43,17]},"f":{"1":0,"2":44},"fnMap":{"1":{"name":"(anonymous_1)","line":3,"loc":{"start":{"line":3,"column":24},"end":{"line":3,"column":43}}},"2":{"name":"(anonymous_2)","line":6,"loc":{"start":{"line":6,"column":21},"end":{"line":6,"column":44}}}},"statementMap":{"1":{"start":{"line":1,"column":0},"end":{"line":1,"column":31}},"2":{"start":{"line":3,"column":0},"end":{"line":5,"column":2}},"3":{"start":{"line":4,"column":2},"end":{"line":4,"column":44}},"4":{"start":{"line":6,"column":0},"end":{"line":89,"column":2}},"5":{"start":{"line":7,"column":2},"end":{"line":7,"column":39}},"6":{"start":{"line":8,"column":2},"end":{"line":17,"column":2}},"7":{"start":{"line":17,"column":2},"end":{"line":19,"column":3}},"8":{"start":{"line":18,"column":4},"end":{"line":18,"column":14}},"9":{"start":{"line":20,"column":2},"end":{"line":24,"column":3}},"10":{"start":{"line":21,"column":4},"end":{"line":21,"column":17}},"11":{"start":{"line":22,"column":4},"end":{"line":22,"column":12}},"12":{"start":{"line":23,"column":4},"end":{"line":23,"column":13}},"13":{"start":{"line":26,"column":2},"end":{"line":26,"column":36}},"14":{"start":{"line":27,"column":2},"end":{"line":27,"column":38}},"15":{"start":{"line":28,"column":2},"end":{"line":28,"column":36}},"16":{"start":{"line":29,"column":2},"end":{"line":29,"column":39}},"17":{"start":{"line":30,"column":2},"end":{"line":30,"column":42}},"18":{"start":{"line":31,"column":2},"end":{"line":31,"column":42}},"19":{"start":{"line":33,"column":2},"end":{"line":36,"column":3}},"20":{"start":{"line":34,"column":4},"end":{"line":34,"column":27}},"21":{"start":{"line":35,"column":4},"end":{"line":35,"column":14}},"22":{"start":{"line":37,"column":2},"end":{"line":40,"column":3}},"23":{"start":{"line":38,"column":4},"end":{"line":38,"column":27}},"24":{"start":{"line":39,"column":4},"end":{"line":39,"column":15}},"25":{"start":{"line":41,"column":2},"end":{"line":44,"column":3}},"26":{"start":{"line":42,"column":4},"end":{"line":42,"column":29}},"27":{"start":{"line":43,"column":4},"end":{"line":43,"column":12}},"28":{"start":{"line":45,"column":2},"end":{"line":54,"column":3}},"29":{"start":{"line":46,"column":4},"end":{"line":47,"column":43}},"30":{"start":{"line":48,"column":4},"end":{"line":52,"column":5}},"31":{"start":{"line":49,"column":6},"end":{"line":49,"column":78}},"32":{"start":{"line":51,"column":6},"end":{"line":51,"column":42}},"33":{"start":{"line":53,"column":4},"end":{"line":53,"column":12}},"34":{"start":{"line":55,"column":2},"end":{"line":58,"column":3}},"35":{"start":{"line":56,"column":4},"end":{"line":56,"column":23}},"36":{"start":{"line":57,"column":4},"end":{"line":57,"column":12}},"37":{"start":{"line":60,"column":2},"end":{"line":60,"column":18}},"38":{"start":{"line":62,"column":2},"end":{"line":62,"column":39}},"39":{"start":{"line":63,"column":2},"end":{"line":63,"column":39}},"40":{"start":{"line":64,"column":2},"end":{"line":64,"column":39}},"41":{"start":{"line":65,"column":2},"end":{"line":65,"column":40}},"42":{"start":{"line":66,"column":2},"end":{"line":66,"column":40}},"43":{"start":{"line":67,"column":2},"end":{"line":67,"column":41}},"44":{"start":{"line":69,"column":2},"end":{"line":71,"column":3}},"45":{"start":{"line":70,"column":4},"end":{"line":70,"column":58}},"46":{"start":{"line":72,"column":2},"end":{"line":74,"column":3}},"47":{"start":{"line":73,"column":4},"end":{"line":73,"column":59}},"48":{"start":{"line":75,"column":2},"end":{"line":77,"column":3}},"49":{"start":{"line":76,"column":4},"end":{"line":76,"column":57}},"50":{"start":{"line":78,"column":2},"end":{"line":80,"column":3}},"51":{"start":{"line":79,"column":4},"end":{"line":79,"column":61}},"52":{"start":{"line":81,"column":2},"end":{"line":83,"column":3}},"53":{"start":{"line":82,"column":4},"end":{"line":82,"column":62}},"54":{"start":{"line":84,"column":2},"end":{"line":86,"column":3}},"55":{"start":{"line":85,"column":4},"end":{"line":85,"column":62}},"56":{"start":{"line":88,"column":2},"end":{"line":88,"column":26}},"57":{"start":{"line":91,"column":0},"end":{"line":91,"column":24}}},"branchMap":{"1":{"line":8,"type":"binary-expr","locations":[{"start":{"line":8,"column":9},"end":{"line":8,"column":13}},{"start":{"line":8,"column":17},"end":{"line":15,"column":3}}]},"2":{"line":17,"type":"if","locations":[{"start":{"line":17,"column":2},"end":{"line":17,"column":2}},{"start":{"line":17,"column":2},"end":{"line":17,"column":2}}]},"3":{"line":20,"type":"if","locations":[{"start":{"line":20,"column":2},"end":{"line":20,"column":2}},{"start":{"line":20,"column":2},"end":{"line":20,"column":2}}]},"4":{"line":33,"type":"if","locations":[{"start":{"line":33,"column":2},"end":{"line":33,"column":2}},{"start":{"line":33,"column":2},"end":{"line":33,"column":2}}]},"5":{"line":37,"type":"if","locations":[{"start":{"line":37,"column":2},"end":{"line":37,"column":2}},{"start":{"line":37,"column":2},"end":{"line":37,"column":2}}]},"6":{"line":41,"type":"if","locations":[{"start":{"line":41,"column":2},"end":{"line":41,"column":2}},{"start":{"line":41,"column":2},"end":{"line":41,"column":2}}]},"7":{"line":45,"type":"if","locations":[{"start":{"line":45,"column":2},"end":{"line":45,"column":2}},{"start":{"line":45,"column":2},"end":{"line":45,"column":2}}]},"8":{"line":48,"type":"if","locations":[{"start":{"line":48,"column":4},"end":{"line":48,"column":4}},{"start":{"line":48,"column":4},"end":{"line":48,"column":4}}]},"9":{"line":55,"type":"if","locations":[{"start":{"line":55,"column":2},"end":{"line":55,"column":2}},{"start":{"line":55,"column":2},"end":{"line":55,"column":2}}]},"10":{"line":69,"type":"if","locations":[{"start":{"line":69,"column":2},"end":{"line":69,"column":2}},{"start":{"line":69,"column":2},"end":{"line":69,"column":2}}]},"11":{"line":69,"type":"binary-expr","locations":[{"start":{"line":69,"column":6},"end":{"line":69,"column":11}},{"start":{"line":69,"column":15},"end":{"line":69,"column":24}}]},"12":{"line":72,"type":"if","locations":[{"start":{"line":72,"column":2},"end":{"line":72,"column":2}},{"start":{"line":72,"column":2},"end":{"line":72,"column":2}}]},"13":{"line":72,"type":"binary-expr","locations":[{"start":{"line":72,"column":6},"end":{"line":72,"column":11}},{"start":{"line":72,"column":15},"end":{"line":72,"column":25}}]},"14":{"line":75,"type":"if","locations":[{"start":{"line":75,"column":2},"end":{"line":75,"column":2}},{"start":{"line":75,"column":2},"end":{"line":75,"column":2}}]},"15":{"line":75,"type":"binary-expr","locations":[{"start":{"line":75,"column":6},"end":{"line":75,"column":11}},{"start":{"line":75,"column":15},"end":{"line":75,"column":23}}]},"16":{"line":78,"type":"if","locations":[{"start":{"line":78,"column":2},"end":{"line":78,"column":2}},{"start":{"line":78,"column":2},"end":{"line":78,"column":2}}]},"17":{"line":78,"type":"binary-expr","locations":[{"start":{"line":78,"column":6},"end":{"line":78,"column":14}},{"start":{"line":78,"column":18},"end":{"line":78,"column":27}}]},"18":{"line":81,"type":"if","locations":[{"start":{"line":81,"column":2},"end":{"line":81,"column":2}},{"start":{"line":81,"column":2},"end":{"line":81,"column":2}}]},"19":{"line":81,"type":"binary-expr","locations":[{"start":{"line":81,"column":6},"end":{"line":81,"column":13}},{"start":{"line":81,"column":17},"end":{"line":81,"column":28}}]},"20":{"line":84,"type":"if","locations":[{"start":{"line":84,"column":2},"end":{"line":84,"column":2}},{"start":{"line":84,"column":2},"end":{"line":84,"column":2}}]},"21":{"line":84,"type":"binary-expr","locations":[{"start":{"line":84,"column":6},"end":{"line":84,"column":13}},{"start":{"line":84,"column":17},"end":{"line":84,"column":28}}]}}}} \ No newline at end of file diff --git a/coverage/lcov.info b/coverage/lcov.info new file mode 100644 index 0000000..6f271d2 --- /dev/null +++ b/coverage/lcov.info @@ -0,0 +1,112 @@ +TN: +SF:/Users/smithm/dev/moment-precise-range/index.js +FN:3,(anonymous_1) +FN:6,(anonymous_2) +FNF:2 +FNH:1 +FNDA:0,(anonymous_1) +FNDA:44,(anonymous_2) +DA:1,1 +DA:3,1 +DA:4,0 +DA:6,1 +DA:7,44 +DA:8,44 +DA:17,44 +DA:18,1 +DA:20,43 +DA:21,1 +DA:22,1 +DA:23,1 +DA:26,43 +DA:27,43 +DA:28,43 +DA:29,43 +DA:30,43 +DA:31,43 +DA:33,43 +DA:34,13 +DA:35,13 +DA:37,43 +DA:38,5 +DA:39,5 +DA:41,43 +DA:42,12 +DA:43,12 +DA:45,43 +DA:46,25 +DA:48,25 +DA:49,4 +DA:51,21 +DA:53,25 +DA:55,43 +DA:56,14 +DA:57,14 +DA:60,43 +DA:62,43 +DA:63,43 +DA:64,43 +DA:65,43 +DA:66,43 +DA:67,43 +DA:69,43 +DA:70,9 +DA:72,43 +DA:73,24 +DA:75,43 +DA:76,23 +DA:78,43 +DA:79,11 +DA:81,43 +DA:82,11 +DA:84,43 +DA:85,12 +DA:88,43 +DA:91,1 +LF:57 +LH:56 +BRDA:8,1,0,44 +BRDA:8,1,1,38 +BRDA:17,2,0,1 +BRDA:17,2,1,43 +BRDA:20,3,0,1 +BRDA:20,3,1,42 +BRDA:33,4,0,13 +BRDA:33,4,1,30 +BRDA:37,5,0,5 +BRDA:37,5,1,38 +BRDA:41,6,0,12 +BRDA:41,6,1,31 +BRDA:45,7,0,25 +BRDA:45,7,1,18 +BRDA:48,8,0,4 +BRDA:48,8,1,21 +BRDA:55,9,0,14 +BRDA:55,9,1,29 +BRDA:69,10,0,9 +BRDA:69,10,1,34 +BRDA:69,11,0,43 +BRDA:69,11,1,9 +BRDA:72,12,0,24 +BRDA:72,12,1,19 +BRDA:72,13,0,43 +BRDA:72,13,1,25 +BRDA:75,14,0,23 +BRDA:75,14,1,20 +BRDA:75,15,0,43 +BRDA:75,15,1,25 +BRDA:78,16,0,11 +BRDA:78,16,1,32 +BRDA:78,17,0,43 +BRDA:78,17,1,14 +BRDA:81,18,0,11 +BRDA:81,18,1,32 +BRDA:81,19,0,43 +BRDA:81,19,1,15 +BRDA:84,20,0,12 +BRDA:84,20,1,31 +BRDA:84,21,0,43 +BRDA:84,21,1,17 +BRF:42 +BRH:42 +end_of_record diff --git a/index.js b/index.js new file mode 100644 index 0000000..dc0c359 --- /dev/null +++ b/index.js @@ -0,0 +1,91 @@ +var moment = require('moment'); + +moment.fn.preciseDiff = function(d2, opts) { + return moment.preciseDiff(this, d2, opts); +}; +moment.preciseDiff = function(d1, d2, opts) { + var m1 = moment(d1), m2 = moment(d2); + opts = opts || { + year: true, + month: true, + day: true, + hour: true, + minute: true, + second: true + } + + if (m1.isSame(m2)) { + return ''; + } + if (m1.isAfter(m2)) { + var tmp = m1; + m1 = m2; + m2 = tmp; + } + + var yDiff = m2.year() - m1.year(); + var mDiff = m2.month() - m1.month(); + var dDiff = m2.date() - m1.date(); + var hourDiff = m2.hour() - m1.hour(); + var minDiff = m2.minute() - m1.minute(); + var secDiff = m2.second() - m1.second(); + + if (secDiff < 0) { + secDiff = 60 + secDiff; + minDiff--; + } + if (minDiff < 0) { + minDiff = 60 + minDiff; + hourDiff--; + } + if (hourDiff < 0) { + hourDiff = 24 + hourDiff; + dDiff--; + } + if (dDiff < 0) { + var daysInLastFullMonth = moment(m2.year() + '-' + (m2.month() + 1), "YYYY-MM") + .subtract(1, 'months').daysInMonth(); + if (daysInLastFullMonth < m1.date()) { // 31/01 -> 2/03 + dDiff = daysInLastFullMonth + dDiff + (m1.date() - daysInLastFullMonth); + } else { + dDiff = daysInLastFullMonth + dDiff; + } + mDiff--; + } + if (mDiff < 0) { + mDiff = 12 + mDiff; + yDiff--; + } + + var result = []; + + moment.relativeTimeThreshold('s',60); + moment.relativeTimeThreshold('m',60); + moment.relativeTimeThreshold('h',23); + moment.relativeTimeThreshold('dd',28); + moment.relativeTimeThreshold('dm',45); + moment.relativeTimeThreshold('dy',365); + + if (yDiff && opts.year) { + result.push(moment.duration(yDiff,'year').humanize()); + } + if (mDiff && opts.month) { + result.push(moment.duration(mDiff,'month').humanize()); + } + if (dDiff && opts.day) { + result.push(moment.duration(dDiff,'day').humanize()); + } + if (hourDiff && opts.hour) { + result.push(moment.duration(hourDiff,'hour').humanize()); + } + if (minDiff && opts.minute) { + result.push(moment.duration(minDiff,'minute').humanize()); + } + if (secDiff && opts.second) { + result.push(moment.duration(secDiff,'second').humanize()); + } + + return result.join(' '); +}; + +module.exports = moment; diff --git a/package.json b/package.json new file mode 100644 index 0000000..9125067 --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "moment-precise-range", + "version": "0.1.0", + "description": "moment js with precision time", + "main": "index.js", + "scripts": { + "test": "mocha", + "coveralls": "istanbul cover _mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage" + }, + "repository": { + "type": "git", + "url": "https://github.com/mtscout6/moment-precise-range.git" + }, + "keywords": [ + "moment" + ], + "author": "Rob Dawson", + "maintainer": "Matthew Smith ", + "license": "MIT", + "bugs": { + "url": "https://github.com/mtscout6/moment-precise-range/issues" + }, + "homepage": "https://github.com/mtscout6/moment-precise-range", + "dependencies": { + "moment": "^2.8.1" + }, + "devDependencies": { + "coveralls": "^2.10.1", + "istanbul": "^0.3.0", + "mocha": "^1.21.4", + "mocha-lcov-reporter": "0.0.1" + } +} diff --git a/readable-range-test.js b/readable-range-test.js deleted file mode 100644 index 6a614f7..0000000 --- a/readable-range-test.js +++ /dev/null @@ -1,121 +0,0 @@ - -describe("preciseDiff", function() { - function test(d1, d2, result) { - expect(moment.preciseDiff(moment(d1, 'YYYY-MM-DD HH:mm:ss'), moment(d2, 'YYYY-MM-DD HH:mm:ss'))).toBe(result); - } - - describe("order", function() { - it("same date", function() { - test('2013-01-01 00:00:00', '2013-01-01 00:00:00', ''); - }); - - it("first date after second", function() { - test('2013-01-01 00:00:01', '2013-01-01 00:00:00', '1 second'); - }); - - it("second date after first", function() { - test('2013-01-01 00:00:00', '2013-01-01 00:00:01', '1 second'); - }); - }); - - describe("single/plural", function() { - it("multiple seconds", function() { - test('2013-01-01 00:00:00', '2013-01-01 00:00:02', '2 seconds'); - }); - - it("one minute", function() { - test('2013-01-01 00:00:00', '2013-01-01 00:01:00', '1 minute'); - }) - - it("multiple minutes", function() { - test('2013-01-01 00:00:00', '2013-01-01 00:02:00', '2 minutes'); - }) - - it("one hour", function() { - test('2013-01-01 00:00:00', '2013-01-01 01:00:00', '1 hour'); - }) - - it("multiple hours", function() { - test('2013-01-01 00:00:00', '2013-01-01 02:00:00', '2 hours'); - }) - - it("one day", function() { - test('2013-01-01 00:00:00', '2013-01-02 00:00:00', '1 day'); - }) - - it("multiple days", function() { - test('2013-01-01 00:00:00', '2013-01-03 00:00:00', '2 days'); - }) - - it("one month", function() { - test('2013-01-01 00:00:00', '2013-02-01 00:00:00', '1 month'); - }) - - it("multiple months", function() { - test('2013-01-01 00:00:00', '2013-03-01 00:00:00', '2 months'); - }) - - it("one year", function() { - test('2013-01-01 00:00:00', '2014-01-01 00:00:00', '1 year'); - }) - - it("multiple years", function() { - test('2013-01-01 00:00:00', '2015-01-01 00:00:00', '2 years'); - }) - }); - - describe("counting back", function() { - it("seconds", function() { - test('2013-01-01 00:02:10', '2013-01-01 00:03:05', '55 seconds'); - }); - it("minutes", function() { - test('2013-01-01 02:10:00', '2013-01-01 03:05:00', '55 minutes'); - }); - it("hours", function() { - test('2013-01-01 23:00:00', '2013-01-02 01:00:00', '2 hours'); - }); - it("days", function() { - test('2013-01-20 00:00:00', '2013-02-10 00:00:00', '21 days'); - }); - it("months", function() { - test('2013-11-01 00:00:00', '2014-02-01 00:00:00', '3 months'); - }); - }); - - describe("days across month boundaries", function() { - it("start month has more days than last full month", function() { - test('2013-01-31 00:00:00', '2013-03-01 00:00:00', '1 month 1 day'); - test('2013-01-30 00:00:00', '2013-03-01 00:00:00', '1 month 1 day'); - test('2013-01-29 00:00:00', '2013-03-01 00:00:00', '1 month 1 day'); - test('2013-01-28 00:00:00', '2013-03-01 00:00:00', '1 month 1 day'); - test('2013-01-27 00:00:00', '2013-03-01 00:00:00', '1 month 2 days'); - - test('2013-05-31 00:00:00', '2013-07-01 00:00:00', '1 month 1 day'); - test('2013-05-30 00:00:00', '2013-07-01 00:00:00', '1 month 1 day'); - test('2013-05-29 00:00:00', '2013-07-01 00:00:00', '1 month 2 days'); - }); - it("start month has fewer days than last full month", function() { - test('2013-04-29 00:00:00', '2013-08-01 00:00:00', '3 months 3 days'); - test('2013-04-30 00:00:00', '2013-08-01 00:00:00', '3 months 2 days'); - // no way to get '3 months 1 day' to 2013-08-01 - }); - it("start month has same days as last full month", function() { - test('2013-05-30 00:00:00', '2013-08-01 00:00:00', '2 months 2 days'); - test('2013-05-31 00:00:00', '2013-08-01 00:00:00', '2 months 1 day'); - }); - }); - - describe("combinations", function() { - it("all values", function() { - test('2001-11-12 13:01:43', '2014-02-01 01:03:01', '12 years 2 months 19 days 12 hours 1 minute 18 seconds'); - }); - it("multiple values", function() { - test('2013-10-21 10:15:40', '2014-02-02 01:01:01', '3 months 11 days 14 hours 45 minutes 21 seconds'); - test('2013-12-31 23:58:10', '2014-01-01 00:02:08', '3 minutes 58 seconds'); - test('2013-12-31 04:08:20', '2014-01-01 01:02:03', '20 hours 53 minutes 43 seconds'); - test('2013-12-27 05:10:20', '2014-01-02 06:12:30', '6 days 1 hour 2 minutes 10 seconds'); - test('2013-10-21 10:15:40', '2014-02-02 01:01:01', '3 months 11 days 14 hours 45 minutes 21 seconds'); - test('2013-11-02 01:00:40', '2014-02-02 01:01:01', '3 months 21 seconds'); - }); - }); -}); \ No newline at end of file diff --git a/readable-range.js b/readable-range.js deleted file mode 100644 index 330c6b1..0000000 --- a/readable-range.js +++ /dev/null @@ -1,91 +0,0 @@ -(function(moment) { - var STRINGS = { - nodiff: '', - year: 'year', - years: 'years', - month: 'month', - months: 'months', - day: 'day', - days: 'days', - hour: 'hour', - hours: 'hours', - minute: 'minute', - minutes: 'minutes', - second: 'second', - seconds: 'seconds', - delimiter: ' ' - }; - moment.fn.preciseDiff = function(d2) { - return moment.preciseDiff(this, d2); - }; - moment.preciseDiff = function(d1, d2) { - var m1 = moment(d1), m2 = moment(d2); - if (m1.isSame(m2)) { - return STRINGS.nodiff; - } - if (m1.isAfter(m2)) { - var tmp = m1; - m1 = m2; - m2 = tmp; - } - - var yDiff = m2.year() - m1.year(); - var mDiff = m2.month() - m1.month(); - var dDiff = m2.date() - m1.date(); - var hourDiff = m2.hour() - m1.hour(); - var minDiff = m2.minute() - m1.minute(); - var secDiff = m2.second() - m1.second(); - - if (secDiff < 0) { - secDiff = 60 + secDiff; - minDiff--; - } - if (minDiff < 0) { - minDiff = 60 + minDiff; - hourDiff--; - } - if (hourDiff < 0) { - hourDiff = 24 + hourDiff; - dDiff--; - } - if (dDiff < 0) { - var daysInLastFullMonth = moment(m2.year() + '-' + (m2.month() + 1), "YYYY-MM").subtract('months', 1).daysInMonth(); - if (daysInLastFullMonth < m1.date()) { // 31/01 -> 2/03 - dDiff = daysInLastFullMonth + dDiff + (m1.date() - daysInLastFullMonth); - } else { - dDiff = daysInLastFullMonth + dDiff; - } - mDiff--; - } - if (mDiff < 0) { - mDiff = 12 + mDiff; - yDiff--; - } - - function pluralize(num, word) { - return num + ' ' + STRINGS[word + (num === 1 ? '' : 's')]; - } - var result = []; - - if (yDiff) { - result.push(pluralize(yDiff, 'year')); - } - if (mDiff) { - result.push(pluralize(mDiff, 'month')); - } - if (dDiff) { - result.push(pluralize(dDiff, 'day')); - } - if (hourDiff) { - result.push(pluralize(hourDiff, 'hour')); - } - if (minDiff) { - result.push(pluralize(minDiff, 'minute')); - } - if (secDiff) { - result.push(pluralize(secDiff, 'second')); - } - - return result.join(STRINGS.delimiter); - }; -}(moment)); diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..d35e38b --- /dev/null +++ b/test/test.js @@ -0,0 +1,153 @@ +// lang = 'en' +var moment = require('../'); +var assert = require('assert'); + +describe('preciseDiff', function() { + function test(d1, d2, result, opts) { + assert.equal( + moment.preciseDiff(moment(d1, 'YYYY-MM-DD HH:mm:ss'), + moment(d2, 'YYYY-MM-DD HH:mm:ss'), opts), + result); + } + + describe('order', function() { + it('same date', function() { + test('2013-01-01 00:00:00', '2013-01-01 00:00:00', ''); + }); + + it('first date after second', function() { + test('2013-01-01 00:00:01', '2013-01-01 00:00:00', 'a few seconds'); + }); + + it('second date after first', function() { + test('2013-01-01 00:00:00', '2013-01-01 00:00:01', 'a few seconds'); + }); + }); + + describe('single/plural', function() { + it('multiple seconds', function() { + test('2013-01-01 00:00:00', '2013-01-01 00:00:02', 'a few seconds'); + }); + + it('one minute', function() { + test('2013-01-01 00:00:00', '2013-01-01 00:01:00', 'a minute'); + }); + + it('multiple minutes', function() { + test('2013-01-01 00:00:00', '2013-01-01 00:02:00', '2 minutes'); + }); + + it('one hour', function() { + test('2013-01-01 00:00:00', '2013-01-01 01:00:00', 'an hour'); + }); + + it('multiple hours', function() { + test('2013-01-01 00:00:00', '2013-01-01 02:00:00', '2 hours'); + }); + + it('one day', function() { + test('2013-01-01 00:00:00', '2013-01-02 00:00:00', 'a day'); + }); + + it('multiple days', function() { + test('2013-01-01 00:00:00', '2013-01-03 00:00:00', '2 days'); + }); + + it('one month', function() { + test('2013-01-01 00:00:00', '2013-02-01 00:00:00', 'a month'); + }); + + it('multiple months', function() { + test('2013-01-01 00:00:00', '2013-03-01 00:00:00', '2 months'); + }); + + it('one year', function() { + test('2013-01-01 00:00:00', '2014-01-01 00:00:00', 'a year'); + }); + + it('multiple years', function() { + test('2013-01-01 00:00:00', '2015-01-01 00:00:00', '2 years'); + }); + }); + + describe('counting back', function() { + it('seconds', function() { + test('2013-01-01 00:02:10', '2013-01-01 00:03:05', 'a few seconds'); + }); + it('minutes', function() { + test('2013-01-01 02:10:00', '2013-01-01 03:05:00', '55 minutes'); + }); + it('hours', function() { + test('2013-01-01 23:00:00', '2013-01-02 01:00:00', '2 hours'); + }); + it('days', function() { + test('2013-01-20 00:00:00', '2013-02-10 00:00:00', '21 days'); + }); + it('months', function() { + test('2013-11-01 00:00:00', '2014-02-01 00:00:00', '3 months'); + }); + }); + + describe('days across month boundaries', function() { + it('start month has more days than last full month', function() { + test('2013-01-31 00:00:00', '2013-03-01 00:00:00', 'a month a day'); + test('2013-01-30 00:00:00', '2013-03-01 00:00:00', 'a month a day'); + test('2013-01-29 00:00:00', '2013-03-01 00:00:00', 'a month a day'); + test('2013-01-28 00:00:00', '2013-03-01 00:00:00', 'a month a day'); + test('2013-01-27 00:00:00', '2013-03-01 00:00:00', 'a month 2 days'); + + test('2013-05-31 00:00:00', '2013-07-01 00:00:00', 'a month a day'); + test('2013-05-30 00:00:00', '2013-07-01 00:00:00', 'a month a day'); + test('2013-05-29 00:00:00', '2013-07-01 00:00:00', 'a month 2 days'); + }); + it('start month has fewer days than last full month', function() { + test('2013-04-29 00:00:00', '2013-08-01 00:00:00', '3 months 3 days'); + test('2013-04-30 00:00:00', '2013-08-01 00:00:00', '3 months 2 days'); + // no way to get '3 months a day' to 2013-08-01 + }); + it('start month has same days as last full month', function() { + test('2013-05-30 00:00:00', '2013-08-01 00:00:00', '2 months 2 days'); + test('2013-05-31 00:00:00', '2013-08-01 00:00:00', '2 months a day'); + }); + }); + + describe('combinations', function() { + it('all values', function() { + test('2001-11-12 13:01:43', '2014-02-01 01:03:01', '12 years 2 months 19 days 12 hours a minute a few seconds'); + }); + it('multiple values', function() { + test('2013-10-21 10:15:40', '2014-02-02 01:01:01', '3 months 11 days 14 hours 45 minutes a few seconds'); + test('2013-12-31 23:58:10', '2014-01-01 00:02:08', '3 minutes a few seconds'); + test('2013-12-31 04:08:20', '2014-01-01 01:02:03', '20 hours 53 minutes a few seconds'); + test('2013-12-27 05:10:20', '2014-01-02 06:12:30', '6 days an hour 2 minutes a few seconds'); + test('2013-10-21 10:15:40', '2014-02-02 01:01:01', '3 months 11 days 14 hours 45 minutes a few seconds'); + test('2013-11-02 01:00:40', '2014-02-02 01:01:01', '3 months a few seconds'); + }); + }); + + describe('precision up till options', function() { + it ('only shows years', function() { + test('2001-11-12 13:01:43', '2014-02-01 01:03:01', '12 years', {year: true}); + }); + + it ('only shows years and months', function() { + test('2001-11-12 13:01:43', '2014-02-01 01:03:01', '12 years 2 months', {year: true, month: true}); + }); + + it('only shows years, months, and days', function() { + test('2001-11-12 13:01:43', '2014-02-01 01:03:01', '12 years 2 months 19 days', {year: true, month: true, day: true}); + }); + + it('only shows years, months, days, and hours', function() { + test('2001-11-12 13:01:43', '2014-02-01 01:03:01', '12 years 2 months 19 days 12 hours', {year: true, month: true, day: true, hour: true}); + }); + + it('only shows years, months, days, hours, and minutes', function() { + test('2001-11-12 13:01:43', '2014-02-01 01:03:01', '12 years 2 months 19 days 12 hours a minute', {year: true, month: true, day: true, hour: true, minute: true}); + }); + + it('only shows years, months, days, hours, minutes, and seconds', function() { + test('2001-11-12 13:01:43', '2014-02-01 01:03:01', '12 years 2 months 19 days 12 hours a minute a few seconds', {year: true, month: true, day: true, hour: true, minute: true, second: true}); + }); + }); +});