]> git.ipfire.org Git - thirdparty/moment.git/commitdiff
Use duration object in relativeTime
authorIskren Chernev <iskren.chernev@gmail.com>
Sun, 27 Apr 2014 20:09:49 +0000 (13:09 -0700)
committerIskren Chernev <iskren.chernev@gmail.com>
Thu, 19 Jun 2014 05:32:16 +0000 (22:32 -0700)
moment.js
test/moment/duration.js
test/moment/lang.js

index ff6641d39d33c51bc62b7781edd65b1e42edf6c8..2d72b5424023e1d69638ee4555e8d817cd3ef8f0 100644 (file)
--- a/moment.js
+++ b/moment.js
 
         // default relative time thresholds
         relativeTimeThresholds = {
-          s: 45,   //seconds to minutes
-          m: 45,   //minutes to hours
-          h: 22,   //hours to days
-          dd: 25,  //days to month (month == 1)
-          dm: 45,  //days to months (months > 1)
-          dy: 345  //days to year
+            s: 45,  // seconds to minute
+            m: 45,  // minutes to hour
+            h: 22,  // hours to day
+            d: 26,  // days to month
+            M: 11   // months to year
         },
 
         // tokens to ordinalize and pad
             y : "a year",
             yy : "%d years"
         },
+
         relativeTime : function (number, withoutSuffix, string, isFuture) {
             var output = this._relativeTime[string];
             return (typeof output === 'function') ?
                 output(number, withoutSuffix, string, isFuture) :
                 output.replace(/%d/i, number);
         },
+
         pastFuture : function (diff, output) {
             var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
             return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
         return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
     }
 
-    function relativeTime(milliseconds, withoutSuffix, lang) {
-        var seconds = round(Math.abs(milliseconds) / 1000),
-            minutes = round(seconds / 60),
-            hours = round(minutes / 60),
-            days = round(hours / 24),
-            years = round(days / 365),
-            args = seconds < relativeTimeThresholds.s  && ['s', seconds] ||
+    function relativeTime(msOrDuration, withoutSuffix, lang) {
+        var duration = (typeof msOrDuration === "number" ?
+                    moment.duration(Math.abs(msOrDuration)) :
+                    moment.duration(msOrDuration).abs()),
+            seconds = round(duration.as('s')),
+            minutes = round(duration.as('m')),
+            hours = round(duration.as('h')),
+            days = round(duration.as('d')),
+            months = round(duration.as('M')),
+            years = round(duration.as('y')),
+
+            args = seconds < relativeTimeThresholds.s && ['s', seconds] ||
                 minutes === 1 && ['m'] ||
                 minutes < relativeTimeThresholds.m && ['mm', minutes] ||
                 hours === 1 && ['h'] ||
                 hours < relativeTimeThresholds.h && ['hh', hours] ||
                 days === 1 && ['d'] ||
-                days <= relativeTimeThresholds.dd && ['dd', days] ||
-                days <= relativeTimeThresholds.dm && ['M'] ||
-                days < relativeTimeThresholds.dy && ['MM', round(days / 30)] ||
+                days < relativeTimeThresholds.d && ['dd', days] ||
+                months === 1 && ['M'] ||
+                months < relativeTimeThresholds.M && ['MM', months] ||
                 years === 1 && ['y'] || ['yy', years];
+
         args[2] = withoutSuffix;
-        args[3] = milliseconds > 0;
+        args[3] = +msOrDuration > 0;
         args[4] = lang;
         return substituteTimeAgo.apply({}, args);
     }
         },
 
         from : function (time, withoutSuffix) {
-            return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
+            return moment.duration({to: this, from: time}).lang(this.lang()._abbr).humanize(!withoutSuffix);
         },
 
         fromNow : function (withoutSuffix) {
     ************************************/
 
 
+    function daysToYears (days) {
+        // 400 years have 146097 days (taking into account leap year rules)
+        return days * 400 / 146097;
+    }
+
+    function yearsToDays (years) {
+        // years * 365 + absRound(years / 4) -
+        //     absRound(years / 100) + absRound(years / 400);
+        return years * 146097 / 400;
+    }
+
     extend(moment.duration.fn = Duration.prototype, {
 
         _bubble : function () {
             days += absRound(hours / 24);
 
             // Accurately convert days to years, assume start from year 0.
-            years = absRound(days * 400 / 146097);
-            days -= years * 365 + absRound(years / 4) -
-                absRound(years / 100) + absRound(years / 400);
+            years = absRound(daysToYears(days));
+            days -= absRound(yearsToDays(years));
 
             // 30 days to a month
             // TODO (iskren): Use anchor date (like 1st Jan) to compute this.
             data.years = years;
         },
 
+        abs : function () {
+            this._milliseconds = Math.abs(this._milliseconds);
+            this._days = Math.abs(this._days);
+            this._months = Math.abs(this._months);
+
+            this._data.milliseconds = Math.abs(this._data.milliseconds);
+            this._data.seconds = Math.abs(this._data.seconds);
+            this._data.minutes = Math.abs(this._data.minutes);
+            this._data.hours = Math.abs(this._data.hours);
+            this._data.months = Math.abs(this._data.months);
+            this._data.years = Math.abs(this._data.years);
+
+            return this;
+        },
+
         weeks : function () {
             return absRound(this.days() / 7);
         },
         },
 
         humanize : function (withSuffix) {
-            var difference = +this,
-                output = relativeTime(difference, !withSuffix, this.lang());
+            var output = relativeTime(this, !withSuffix, this.lang());
 
             if (withSuffix) {
-                output = this.lang().pastFuture(difference, output);
+                output = this.lang().pastFuture(+this, output);
             }
 
             return this.lang().postformat(output);
         },
 
         as : function (units) {
+            var days, months;
             units = normalizeUnits(units);
-            return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
+
+            days = this._days + this._milliseconds / 864e5;
+            if (units === 'month' || units === 'year') {
+                months = this._months + daysToYears(days) * 12;
+                return units === 'month' ? months : months / 12;
+            } else {
+                days += yearsToDays(this._months / 12);
+                switch (units) {
+                    case 'week': return days / 7;
+                    case 'day': return days;
+                    case 'hour': return days * 24;
+                    case 'minute': return days * 24 * 60;
+                    case 'second': return days * 24 * 60 * 60;
+                    case 'millisecond': return days * 24 * 60 * 60 * 1000;
+                    default: throw new Error("Unknown unit " + units);
+                }
+            }
         },
 
         lang : moment.fn.lang,
         };
     }
 
-    function makeDurationAsGetter(name, factor) {
-        moment.duration.fn['as' + name] = function () {
-            return +this / factor;
-        };
-    }
-
     for (i in unitMillisecondFactors) {
         if (unitMillisecondFactors.hasOwnProperty(i)) {
-            makeDurationAsGetter(i, unitMillisecondFactors[i]);
             makeDurationGetter(i.toLowerCase());
         }
     }
 
-    makeDurationAsGetter('Weeks', 6048e5);
-    moment.duration.fn.asMonths = function () {
-        return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
-    };
-
+    moment.duration.fn.asMilliseconds = function () { return this.as('ms'); };
+    moment.duration.fn.asSeconds = function () { return this.as('s'); };
+    moment.duration.fn.asMinutes = function () { return this.as('m'); };
+    moment.duration.fn.asHours = function () { return this.as('h'); };
+    moment.duration.fn.asDays = function () { return this.as('d'); };
+    moment.duration.fn.asWeeks = function () { return this.as('weeks'); };
+    moment.duration.fn.asMonths = function () { return this.as('M'); };
+    moment.duration.fn.asYears = function () { return this.as('Y'); };
 
     /************************************
         Default Lang
index 39673d8d5c705edafbb4d2327ccca540f57bb698..a37ee2c579d8f3a20891e571ed9bd98efd61d80f 100644 (file)
@@ -357,13 +357,13 @@ exports.duration = {
         test.equal(moment.duration({days: 25}).humanize(),     "25 days",       "25 days = 25 days");
         test.equal(moment.duration({days: 26}).humanize(),     "a month",       "26 days = a month");
         test.equal(moment.duration({days: 30}).humanize(),     "a month",       "30 days = a month");
-        test.equal(moment.duration({days: 45}).humanize(),     "a month",       "45 days = a month");
+        test.equal(moment.duration({days: 45}).humanize(),     "2 months",       "45 days = 2 months");
         test.equal(moment.duration({days: 46}).humanize(),     "2 months",      "46 days = 2 months");
         test.equal(moment.duration({days: 74}).humanize(),     "2 months",      "75 days = 2 months");
         test.equal(moment.duration({days: 76}).humanize(),     "3 months",      "76 days = 3 months");
         test.equal(moment.duration({months: 1}).humanize(),    "a month",       "1 month = a month");
         test.equal(moment.duration({months: 5}).humanize(),    "5 months",      "5 months = 5 months");
-        test.equal(moment.duration({days: 344}).humanize(),    "11 months",     "344 days = 11 months");
+        test.equal(moment.duration({days: 344}).humanize(),    "a year",        "344 days = a year");
         test.equal(moment.duration({days: 345}).humanize(),    "a year",        "345 days = a year");
         test.equal(moment.duration({days: 547}).humanize(),    "a year",        "547 days = a year");
         test.equal(moment.duration({days: 548}).humanize(),    "2 years",       "548 days = 2 years");
index 405b1a2aac762e506c56cd4fb6868a2dd7aa956b..957b217c71540ae3a814cb4bb3c4af7ef0755204 100644 (file)
@@ -202,6 +202,80 @@ exports.lang = {
         test.done();
     },
 
+    "from relative time future" : function (test) {
+        var start = moment([2007, 1, 28]);
+
+        test.equal(start.from(moment([2007, 1, 28]).subtract({s: 44})),  "in a few seconds", "44 seconds = a few seconds");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({s: 45})),  "in a minute",      "45 seconds = a minute");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({s: 89})),  "in a minute",      "89 seconds = a minute");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({s: 90})),  "in 2 minutes",     "90 seconds = 2 minutes");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({m: 44})),  "in 44 minutes",    "44 minutes = 44 minutes");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({m: 45})),  "in an hour",       "45 minutes = an hour");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({m: 89})),  "in an hour",       "89 minutes = an hour");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({m: 90})),  "in 2 hours",       "90 minutes = 2 hours");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({h: 5})),   "in 5 hours",       "5 hours = 5 hours");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({h: 21})),  "in 21 hours",      "21 hours = 21 hours");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({h: 22})),  "in a day",         "22 hours = a day");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({h: 35})),  "in a day",         "35 hours = a day");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({h: 36})),  "in 2 days",        "36 hours = 2 days");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 1})),   "in a day",         "1 day = a day");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 5})),   "in 5 days",        "5 days = 5 days");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 25})),  "in 25 days",       "25 days = 25 days");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 26})),  "in a month",       "26 days = a month");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 30})),  "in a month",       "30 days = a month");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 45})),  "in a month",       "45 days = a month");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 46})),  "in 2 months",      "46 days = 2 months");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 74})),  "in 2 months",      "75 days = 2 months");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 76})),  "in 3 months",      "76 days = 3 months");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({M: 1})),   "in a month",       "1 month = a month");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({M: 5})),   "in 5 months",      "5 months = 5 months");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 344})), "in 11 months",     "344 days = 11 months");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 345})), "in a year",        "345 days = a year");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 547})), "in a year",        "547 days = a year");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({d: 548})), "in a year",        "548 days = a year");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({y: 1})),   "in a year",        "1 year = a year");
+        test.equal(start.from(moment([2007, 1, 28]).subtract({y: 5})),   "in 5 years",       "5 years = 5 years");
+
+        test.done();
+    },
+
+    "from relative time past" : function (test) {
+        var start = moment([2007, 1, 28]);
+
+        test.equal(start.from(moment([2007, 1, 28]).add({s: 44})),  "a few seconds ago", "44 seconds = a few seconds");
+        test.equal(start.from(moment([2007, 1, 28]).add({s: 45})),  "a minute ago",      "45 seconds = a minute");
+        test.equal(start.from(moment([2007, 1, 28]).add({s: 89})),  "a minute ago",      "89 seconds = a minute");
+        test.equal(start.from(moment([2007, 1, 28]).add({s: 90})),  "2 minutes ago",     "90 seconds = 2 minutes");
+        test.equal(start.from(moment([2007, 1, 28]).add({m: 44})),  "44 minutes ago",    "44 minutes = 44 minutes");
+        test.equal(start.from(moment([2007, 1, 28]).add({m: 45})),  "an hour ago",       "45 minutes = an hour");
+        test.equal(start.from(moment([2007, 1, 28]).add({m: 89})),  "an hour ago",       "89 minutes = an hour");
+        test.equal(start.from(moment([2007, 1, 28]).add({m: 90})),  "2 hours ago",       "90 minutes = 2 hours");
+        test.equal(start.from(moment([2007, 1, 28]).add({h: 5})),   "5 hours ago",       "5 hours = 5 hours");
+        test.equal(start.from(moment([2007, 1, 28]).add({h: 21})),  "21 hours ago",      "21 hours = 21 hours");
+        test.equal(start.from(moment([2007, 1, 28]).add({h: 22})),  "a day ago",         "22 hours = a day");
+        test.equal(start.from(moment([2007, 1, 28]).add({h: 35})),  "a day ago",         "35 hours = a day");
+        test.equal(start.from(moment([2007, 1, 28]).add({h: 36})),  "2 days ago",        "36 hours = 2 days");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 1})),   "a day ago",         "1 day = a day");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 5})),   "5 days ago",        "5 days = 5 days");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 25})),  "25 days ago",       "25 days = 25 days");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 26})),  "a month ago",       "26 days = a month");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 30})),  "a month ago",       "30 days = a month");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 45})),  "2 months ago",       "45 days = 2 months");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 46})),  "2 months ago",      "46 days = 2 months");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 74})),  "2 months ago",      "75 days = 2 months");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 76})),  "3 months ago",      "76 days = 3 months");
+        test.equal(start.from(moment([2007, 1, 28]).add({M: 1})),   "a month ago",       "1 month = a month");
+        test.equal(start.from(moment([2007, 1, 28]).add({M: 5})),   "5 months ago",      "5 months = 5 months");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 344})), "11 months ago",     "344 days = 11 months");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 345})), "a year ago",        "345 days = a year");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 547})), "a year ago",        "547 days = a year");
+        test.equal(start.from(moment([2007, 1, 28]).add({d: 548})), "a year ago",       "548 days = a year");
+        test.equal(start.from(moment([2007, 1, 28]).add({y: 1})),   "a year ago",        "1 year = a year");
+        test.equal(start.from(moment([2007, 1, 28]).add({y: 5})),   "5 years ago",       "5 years = 5 years");
+
+        test.done();
+    },
+
     "instance lang used with from" : function (test) {
         test.expect(2);
         moment.lang('en');