diff --git a/lib/BUCK b/lib/BUCK
index f21f207647..9e5c5c3098 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -15,6 +15,7 @@ define_license(name = 'h2')
define_license(name = 'jgit')
define_license(name = 'jsch')
define_license(name = 'MPL1.1')
+define_license(name = 'moment')
define_license(name = 'ow2')
define_license(name = 'page.js')
define_license(name = 'polymer')
@@ -258,4 +259,3 @@ maven_jar(
sha1 = 'd9a09f7732226af26bf99f19e2cffe0ae219db5b',
license = 'DO_NOT_DISTRIBUTE',
)
-
diff --git a/lib/LICENSE-moment b/lib/LICENSE-moment
new file mode 100644
index 0000000000..9ee537448a
--- /dev/null
+++ b/lib/LICENSE-moment
@@ -0,0 +1,22 @@
+Copyright (c) 2011-2016 Tim Wood, Iskren Chernev, Moment.js contributors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/js/BUCK b/lib/js/BUCK
index 948f9b47bf..b0bdb67ce3 100644
--- a/lib/js/BUCK
+++ b/lib/js/BUCK
@@ -256,6 +256,14 @@ bower_component(
sha1 = '5a68250d6d9abcd576f116dc4fc7312426323883',
)
+bower_component(
+ name = 'moment',
+ package = 'moment/moment',
+ version = '2.12.0',
+ license = 'moment',
+ sha1 = '508d53de8f49ab87f03e209e5073e339107ed3e6',
+)
+
bower_component(
name = 'neon-animation',
package = 'polymerelements/neon-animation',
diff --git a/polygerrit-ui/BUCK b/polygerrit-ui/BUCK
index 0a562f9329..4d8144ffb7 100644
--- a/polygerrit-ui/BUCK
+++ b/polygerrit-ui/BUCK
@@ -10,6 +10,7 @@ bower_components(
'//lib/js:iron-input',
'//lib/js:iron-overlay-behavior',
'//lib/js:iron-selector',
+ '//lib/js:moment',
'//lib/js:page',
'//lib/js:polymer',
'//lib/js:promise-polyfill',
diff --git a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.html b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.html
index 6d4b2ea71d..01deeda1f7 100644
--- a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.html
+++ b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.html
@@ -15,6 +15,9 @@ limitations under the License.
-->
+
+
+
@@ -23,7 +26,8 @@ limitations under the License.
display: inline;
}
- [[_computeDateStr(dateStr)]]
+ [[_computeDateStr(dateStr, timeFormat)]]
+
diff --git a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js
index cb77cc13ad..35347f5ddf 100644
--- a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js
+++ b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js
@@ -19,10 +19,12 @@
DAY: 1000 * 60 * 60 * 24,
};
- var ShortMonthNames = [
- 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
- 'Nov', 'Dec'
- ];
+ var TimeFormats = {
+ TIME_12: 'h:mm A', // 2:14 PM
+ TIME_24: 'H:mm', // 14:14
+ MONTH_DAY: 'MMM DD', // Aug 29
+ MONTH_DAY_YEAR: 'MMM DD, YYYY', // Aug 29, 1997
+ };
Polymer({
is: 'gr-date-formatter',
@@ -31,46 +33,58 @@
dateStr: {
type: String,
value: null,
- notify: true
- }
+ notify: true,
+ },
+ timeFormat: {
+ type: String,
+ value: 'HHMM_24',
+ notify: true,
+ },
},
- _computeDateStr: function(dateStr) {
- return this._dateStr(this._parseDateStr(dateStr), new Date());
+ attached: function() {
+ this._fetchPreferences();
},
- _parseDateStr: function(dateStr) {
- if (!dateStr) { return null; }
- return util.parseDate(dateStr);
+ _fetchPreferences: function() {
+ this.$.restAPI.getPreferences().then(function(preferences) {
+ this.timeFormat = preferences && preferences.time_format;
+ }.bind(this));
},
- _dateStr: function(t, now) {
- if (!t) { return ''; }
- var diff = now.getTime() - t.getTime();
- if (diff < Duration.DAY && t.getDay() == now.getDay()) {
- // Within 24 hours and on the same day:
- // '2:14 AM'
- var pm = t.getHours() >= 12;
- var hours = t.getHours();
- if (hours == 0) {
- hours = 12;
- } else if (hours > 12) {
- hours = t.getHours() - 12;
+ /**
+ * Return true if date is within 24 hours and on the same day.
+ */
+ _isWithinDay: function(now, date) {
+ var diff = -date.diff(now);
+ return diff < Duration.DAY && date.day() == now.getDay();
+ },
+
+ /**
+ * Returns true if date is from one to six months.
+ */
+ _isWithinHalfYear: function(now, date) {
+ var diff = -date.diff(now);
+ return (date.day() != now.getDay() || diff >= Duration.DAY) &&
+ diff < 180 * Duration.DAY;
+ },
+
+ _computeDateStr: function(dateStr, timeFormat) {
+ if (!dateStr) { return ''; }
+ var date = moment(dateStr + 'Z');
+ if (!date.isValid()) { return ''; }
+ var now = new Date();
+ var format = TimeFormats.MONTH_DAY_YEAR;
+ if (this._isWithinDay(now, date)) {
+ if (this.timeFormat == 'HHMM_12') {
+ format = TimeFormats.TIME_12;
+ } else {
+ format = TimeFormats.TIME_24;
}
- var minutes = t.getMinutes() < 10 ? '0' + t.getMinutes() :
- t.getMinutes();
- return hours + ':' + minutes + (pm ? ' PM' : ' AM');
- } else if ((t.getDay() != now.getDay() || diff >= Duration.DAY) &&
- diff < 180 * Duration.DAY) {
- // From one to six months:
- // 'Aug 29'
- return ShortMonthNames[t.getMonth()] + ' ' + t.getDate();
- } else if (diff >= 180 * Duration.DAY) {
- // More than six months:
- // 'Aug 29, 1997'
- return ShortMonthNames[t.getMonth()] + ' ' + t.getDate() + ', ' +
- t.getFullYear();
+ } else if (this._isWithinHalfYear(now, date)) {
+ format = TimeFormats.MONTH_DAY;
}
+ return date.format(format);
},
});
})();
diff --git a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html
index 9bba517ece..932cba4962 100644
--- a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html
@@ -34,51 +34,107 @@ limitations under the License.
suite('gr-date-formatter tests', function() {
var element;
- setup(function() {
- element = fixture('basic');
- });
-
- test('date is parsed correctly', function() {
- assert.notOk((new Date('foo')).valueOf());
- var d = element._parseDateStr(element.getAttribute('date-str'));
- assert.isAbove(d.valueOf(), 0);
- });
-
+ /**
+ * Parse server-formatter date and normalize into current timezone.
+ */
function normalizedDate(dateStr) {
- var d = new Date(dateStr);
+ var d = new Date(util.parseDate(dateStr));
d.setMinutes(d.getMinutes() + d.getTimezoneOffset());
return d;
}
function testDates(nowStr, dateStr, expected) {
- var now = normalizedDate(nowStr);
- var t = normalizedDate(dateStr);
- assert.equal(element._dateStr(t, now), expected);
+ // Normalize and convert the date to mimic server response.
+ dateStr = normalizedDate(dateStr)
+ .toJSON().replace('T', ' ').slice(0, -1);
+ var clock = sinon.useFakeTimers(
+ new Date(normalizedDate(nowStr)).getTime());
+ element.dateStr = dateStr;
+ assert.equal(element.$$('span').textContent, expected);
+ clock.restore();
}
- test('dates strings are correct', function() {
- // Within 24 hours on same day.
- testDates('2015-07-29T20:34:00.000Z',
- '2015-07-29T15:34:00.000Z',
- '3:34 PM');
- testDates('2016-01-27T17:41:00.000Z',
- '2016-01-27T12:41:00.000Z',
- '12:41 PM');
+ function stubPreferences(preferences) {
+ var preferencesPromise = Promise.resolve(preferences);
+ stub('gr-rest-api-interface', {
+ getPreferences: sinon.stub().returns(preferencesPromise),
+ });
+ return preferencesPromise;
+ }
- // Within 24 hours on different days.
- testDates('2015-07-29T03:34:00.000Z',
- '2015-07-28T20:25:00.000Z',
- 'Jul 28');
+ suite('not signed in', function() {
+ setup(function() {
+ return stubPreferences(null).then(function() {
+ element = fixture('basic');
+ });
+ });
- // More than 24 hours. Less than six months.
- testDates('2015-07-29T20:34:00.000Z',
- '2015-06-15T03:25:00.000Z',
- 'Jun 15');
+ test('invalid dates are quietly rejected', function() {
+ assert.notOk((new Date('foo')).valueOf());
+ element.dateStr = 'foo';
+ assert.equal(element.$$('span').textContent, '');
+ });
- // More than six months.
- testDates('2015-09-15T20:34:00.000Z',
- '2015-01-15T03:25:00.000Z',
- 'Jan 15, 2015');
+ test('Within 24 hours on same day', function() {
+ testDates('2015-07-29 20:34:14.985000000',
+ '2015-07-29 15:34:14.985000000',
+ '15:34');
+ testDates('2016-01-27 17:41:14.985000000',
+ '2016-01-27 12:41:14.985000000',
+ '12:41');
+ });
+
+ test('Within 24 hours on different days', function() {
+ testDates('2015-07-29 03:34:14.985000000',
+ '2015-07-28 20:25:14.985000000',
+ 'Jul 28');
+ });
+
+ test('More than 24 hours but less than six months', function() {
+ testDates('2015-07-29 20:34:14.985000000',
+ '2015-06-15 03:25:14.985000000',
+ 'Jun 15');
+ });
+
+ test('More than six months', function() {
+ testDates('2015-09-15 20:34:00.000000000',
+ '2015-01-15 03:25:00.000000000',
+ 'Jan 15, 2015');
+ });
+ });
+
+ suite('signed in with 12 hours time format preference', function() {
+ setup(function() {
+ return stubPreferences({time_format: 'HHMM_12'}).then(function() {
+ element = fixture('basic');
+ });
+ });
+
+ test('Within 24 hours on same day', function() {
+ testDates('2015-07-29 20:34:14.985000000',
+ '2015-07-29 15:34:14.985000000',
+ '3:34 PM');
+ testDates('2016-01-27 17:41:14.985000000',
+ '2016-01-27 12:41:14.985000000',
+ '12:41 PM');
+ });
+ });
+
+ suite('signed in with 24 hours time format preference', function() {
+ setup(function() {
+ return stubPreferences({time_format: 'HHMM_24'}).then(function() {
+ element = fixture('basic');
+ });
+ });
+
+ test('Within 24 hours on same day', function() {
+ testDates('2015-07-29 20:34:14.985000000',
+ '2015-07-29 15:34:14.985000000',
+ '15:34');
+ testDates('2016-01-27 17:41:14.985000000',
+ '2016-01-27 12:41:14.985000000',
+ '12:41');
+ });
});
});