diff --git a/readable-range-test.js b/readable-range-test.js index 6a614f7..985e550 100644 --- a/readable-range-test.js +++ b/readable-range-test.js @@ -1,121 +1,121 @@ - +// lang = 'en' 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 + 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', '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'); + }); + }); +}); diff --git a/readable-range.js b/readable-range.js index 330c6b1..cd65337 100644 --- a/readable-range.js +++ b/readable-range.js @@ -1,91 +1,97 @@ (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(); + moment.fn.preciseDiff = function(d2) { + return moment.preciseDiff(this, d2); + }; + moment.preciseDiff = function(d1, d2) { - 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--; - } + var m1 = moment(d1), m2 = moment(d2); + if (m1.isSame(m2)) { + return ''; + } + if (m1.isAfter(m2)) { + var tmp = m1; + m1 = m2; + m2 = tmp; + } - function pluralize(num, word) { - return num + ' ' + STRINGS[word + (num === 1 ? '' : 's')]; - } - var result = []; + 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 (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')); - } + 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--; + } + + var result = []; + + var originalRelative = {}; + originalRelative.s = moment.relativeTimeThreshold('s'); + originalRelative.m = moment.relativeTimeThreshold('m'); + originalRelative.h = moment.relativeTimeThreshold('h'); + originalRelative.dd = moment.relativeTimeThreshold('dd'); + originalRelative.dm = moment.relativeTimeThreshold('dm'); + originalRelative.dy = moment.relativeTimeThreshold('dy'); + + 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) { + result.push(moment.duration(yDiff,'year').humanize()); + } + if (mDiff) { + result.push(moment.duration(mDiff,'month').humanize()) + } + if (dDiff) { + result.push(moment.duration(dDiff,'day').humanize()); + } + if (hourDiff) { + result.push(moment.duration(hourDiff,'hour').humanize()); + } + if (minDiff) { + result.push(moment.duration(minDiff,'minute').humanize()); + } + if (secDiff) { + result.push(moment.duration(secDiff,'second').humanize()); + } + + moment.relativeTimeThreshold('s',originalRelative.s); + moment.relativeTimeThreshold('m',originalRelative.m); + moment.relativeTimeThreshold('h',originalRelative.h); + moment.relativeTimeThreshold('dd',originalRelative.dd); + moment.relativeTimeThreshold('dm',originalRelative.dm); + moment.relativeTimeThreshold('dy',originalRelative.dy); + + return result.join(' '); + }; - return result.join(STRINGS.delimiter); - }; }(moment));