Recognize time format preferences.

Bug: Issue 3779
Change-Id: I94d9e8f7a6e688d49be6c22c43b0240ca6768894
This commit is contained in:
Viktar Donich 2016-03-15 15:17:06 -07:00
parent ae004a56bd
commit 290fcb6125
7 changed files with 177 additions and 72 deletions

View File

@ -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',
)

22
lib/LICENSE-moment Normal file
View File

@ -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.

View File

@ -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',

View File

@ -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',

View File

@ -15,6 +15,9 @@ limitations under the License.
-->
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../gr-rest-api-interface/gr-rest-api-interface.html">
<script src="../../../bower_components/moment/moment.js"></script>
<dom-module id="gr-date-formatter">
<template>
@ -23,7 +26,8 @@ limitations under the License.
display: inline;
}
</style>
<span>[[_computeDateStr(dateStr)]]</span>
<span>[[_computeDateStr(dateStr, timeFormat)]]</span>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
</template>
<script src="gr-date-formatter.js"></script>
</dom-module>

View File

@ -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);
},
});
})();

View File

@ -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');
});
});
});
</script>