fix date/time representation in national locales
Added "localeDate" filter to present date and time in preferred format:
- the date will be displayed as: 'Dec 3, 2018'
- the time will be displayed in locale preferred format.
- the timezone will be displayed as abbrev or GMT+/-offset.
At the 'Date and Time setting' the time zone name will displayed in long
format if it is possible.
All text parts of date/time representation will be in English.
Resolves: openbmc/phosphor-webui#42
Change-Id: I2fdbb47c62dfc5000039b0c00a20f64a9a389fc6
Signed-off-by: Alexander Filippov <a.filippov@yadro.com>
diff --git a/app/common/directives/app-header.html b/app/common/directives/app-header.html
index d0c2aa6..0b473ed 100644
--- a/app/common/directives/app-header.html
+++ b/app/common/directives/app-header.html
@@ -16,7 +16,7 @@
<i class="icon icon-angle" aria-hidden="true"></i><span ng-class="{'status-light__error': dataService.server_health == 'Critical', 'status-light__warn': dataService.server_health == 'Warning', 'status-light__good': dataService.server_health == 'Good'}">{{dataService.server_health}}</span></a>
<a href="#/server-control/power-operations" class="header__server-power" role="button">Server power
<i class="icon icon-angle" aria-hidden="true"></i><span ng-class="{'status-light__off': dataService.server_state == 'Off', 'status-light__disabled': dataService.server_state == 'Unreachable', 'status-light__good': dataService.server_state == 'Running', 'status-light__error': dataService.server_state == 'Quiesced'}">{{dataService.server_state | quiescedToError}}</span></a>
- <p class="header__refresh">Data last refreshed<span>{{dataService.last_updated | date:'medium'}}</span>
+ <p class="header__refresh">Data last refreshed<span>{{dataService.last_updated | localeDate}}</span>
</p>
<button class="header__page-refresh" ng-click="refresh()" aria-label="refresh page data">
<span>Refresh</span>
diff --git a/app/common/directives/log-event.html b/app/common/directives/log-event.html
index 3ec3c91..344dccb 100644
--- a/app/common/directives/log-event.html
+++ b/app/common/directives/log-event.html
@@ -24,7 +24,7 @@
<p class="inline event__priority event-resolved" ng-hide="event.Resolved == 0">Resolved</p>
<p class="inline event__priority" ng-class="{'low-priority': event.priority == 'Low', 'medium-priority': event.priority == 'Medium', 'high-priority': event.priority == 'High'}">{{event.priority}}</p>
<p class="inline event__severity" ng-class="{'low-priority': event.priority == 'Low', 'medium-priority': event.priority == 'Medium', 'high-priority': event.priority == 'High'}">{{event.severity_code}}</p>
- <p class="event__timestamp">{{(tmz == 'UTC' ? (event.Timestamp | date:'medium': tmz) : (event.Timestamp | date:'medium')) + ' ' + tmz}}</p>
+ <p class="event__timestamp">{{ event.Timestamp | localeDate : (tmz =='UTC') }}</p>
<div>
<p class="inline event__description">{{getTitle(event)}}</p>
</div>
diff --git a/app/common/filters/index.js b/app/common/filters/index.js
index 3c6f26a..c760158 100644
--- a/app/common/filters/index.js
+++ b/app/common/filters/index.js
@@ -12,13 +12,44 @@
return data.length;
}
})
- .filter('quiescedToError', function() {
- return function(state) {
- if (state.toLowerCase() == 'quiesced') {
- return 'Error';
- } else {
- return state;
+ .filter(
+ 'quiescedToError',
+ function() {
+ return function(state) {
+ if (state.toLowerCase() == 'quiesced') {
+ return 'Error';
+ } else {
+ return state;
+ }
+ }
+ })
+ .filter('localeDate', function() {
+ return function(timestamp, utc = false) {
+ var dt = new Date(timestamp);
+ if (isNaN(dt)) {
+ return 'not available';
}
+
+ const ro = Intl.DateTimeFormat().resolvedOptions();
+ var tz = 'UTC';
+ if (!utc) {
+ tz = ro.timeZone;
+ }
+
+ // Examples:
+ // "Dec 3, 2018 11:35:01 AM CST" for en-US at 'America/Chicago'
+ // "Dec 3, 2018 5:35:01 PM UTC" for en-US at 'UTC'
+ // "Dec 3, 2018 17:35:01 GMT" for en-GB at 'Europe/London'
+ // "Dec 3, 2018 20:35:01 GMT+3" for ru-RU at 'Europe/Moscow'
+ // "Dec 3, 2018 17:35:01 UTC" for ru-RU at 'UTC'
+ return dt.toLocaleDateString('en-US', {
+ timeZone: tz,
+ month: 'short',
+ year: 'numeric',
+ day: 'numeric'
+ }) + ' ' +
+ dt.toLocaleTimeString(
+ ro.locale, {timeZone: tz, timeZoneName: 'short'});
}
});
})(window.angular);
diff --git a/app/configuration/controllers/date-time-controller.js b/app/configuration/controllers/date-time-controller.js
index 5d2459d..a08a141 100644
--- a/app/configuration/controllers/date-time-controller.js
+++ b/app/configuration/controllers/date-time-controller.js
@@ -35,19 +35,20 @@
new Date(data.data[timePath + 'bmc'].Elapsed / 1000);
// Don't care about milliseconds and don't want them displayed
$scope.bmc.date.setMilliseconds(0);
- // https://stackoverflow.com/questions/1091372/getting-the-clients-timezone-in-javascript
- // EDT (UTC - 04:00)
- $scope.bmc.timezone =
- $scope.bmc.date.toString().match(/\(([A-Za-z\s].*)\)/)[1] +
- ' ' + createOffset($scope.bmc.date);
+
+ // Examples:
+ // Central Standard Time (UTC-06:00)
+ // Moscow Standard Time (UTC+03:00)
+ $scope.bmc.timezone = getUserTimezone($scope.bmc.date) + ' ' +
+ createOffset($scope.bmc.date);
}
if (data.data[timePath + 'host'] &&
data.data[timePath + 'host'].hasOwnProperty('Elapsed')) {
$scope.host.date =
new Date(data.data[timePath + 'host'].Elapsed / 1000);
$scope.host.date.setMilliseconds(0);
- $scope.host.timezone =
- $scope.host.date.toString().match(/([A-Z]+[\+-][0-9]+.*)/)[1];
+ $scope.host.timezone = getUserTimezone($scope.bmc.date) + ' ' +
+ createOffset($scope.bmc.date);
}
if (data.data[timePath + 'owner'] &&
data.data[timePath + 'owner'].hasOwnProperty('TimeOwner')) {
@@ -193,6 +194,22 @@
var minutes = pad(offset % 60);
return '(UTC' + sign + hours + ':' + minutes + ')';
}
+ function getUserTimezone(date) {
+ const ro = Intl.DateTimeFormat().resolvedOptions();
+ // A safe, easy way to get the timezone (e.g. Central Standard Time) is
+ // to subtract the time string without a timezone from the time string
+ // with a timezone.
+ // Hardcoded to 'en-US' so all timezones are displayed in English
+ // (e.g. Moscow Standard Time).
+ var ret = date.toLocaleTimeString('en-US', {timeZoneName: 'long'})
+ .replace(date.toLocaleTimeString('en-US'), '')
+ .trim();
+ // Do not return GMT+/-offset.
+ if (ret.indexOf('GMT') >= 0) {
+ return '';
+ }
+ return ret;
+ }
function pad(value) {
return value < 10 ? '0' + value : value;
}
diff --git a/app/overview/controllers/system-overview-controller.html b/app/overview/controllers/system-overview-controller.html
index a548675..e9e189c 100644
--- a/app/overview/controllers/system-overview-controller.html
+++ b/app/overview/controllers/system-overview-controller.html
@@ -85,7 +85,7 @@
</a>
<div class="quick-links__item no-icon">
<p class="inline quick-links__label">BMC time</p>
- <p class="inline courier-bold float-right bmc-time">{{(bmc_time | date:'medium') + ' ' + tmz}}</p>
+ <p class="inline courier-bold float-right bmc-time">{{ bmc_time | localeDate }}</p>
</div>
<div class="quick-links__item no-icon">
<p class="inline quick-links__label">Turn <span ng-if="dataService.LED_state == 'off'">on</span><span ng-if="dataService.LED_state == 'on'">off</span> server LED</p>
@@ -125,7 +125,7 @@
<p class="inline event__id">#{{event.Id}}</p>
<p class="inline event__priority high-priority">High</p>
<p class="inline event__severity high-priority">{{event.severity_code}}</p>
- <p class="inline event__timestamp">{{(event.Timestamp | date:'medium') + ' ' + tmz}}</p>
+ <p class="inline event__timestamp">{{ event.Timestamp | localeDate }}</p>
<div>
<p class="inline event__description">{{getEventLogTitle(event)}}</p>
</div>
diff --git a/app/overview/controllers/system-overview-controller.js b/app/overview/controllers/system-overview-controller.js
index 6393ebc..0b7d2f0 100644
--- a/app/overview/controllers/system-overview-controller.js
+++ b/app/overview/controllers/system-overview-controller.js
@@ -14,7 +14,6 @@
function($scope, $window, APIUtils, dataService, Constants, $q) {
$scope.dataService = dataService;
$scope.dropdown_selected = false;
- $scope.tmz = getUserTimezone();
$scope.logs = [];
$scope.server_info = {};
$scope.bmc_firmware = '';
@@ -159,9 +158,6 @@
}
return title;
};
- function getUserTimezone() {
- return new Date().toString().match(/\(([A-Za-z\s].*)\)/)[1];
- }
}
]);
})(angular);
diff --git a/app/server-control/controllers/bmc-reboot-controller.html b/app/server-control/controllers/bmc-reboot-controller.html
index 8b987a3..dece701 100644
--- a/app/server-control/controllers/bmc-reboot-controller.html
+++ b/app/server-control/controllers/bmc-reboot-controller.html
@@ -6,7 +6,7 @@
<div class="page-header">
<p class="inline h4">Current BMC boot status</p>
<div class="float-right bmc-reboot__status-log inline">BMC last reboot at
- <span class="courier-bold">{{reboot_time | date:'medium'}}</span></div>
+ <span class="courier-bold">{{reboot_time | localeDate}}</span></div>
</div>
</div>
<div class="row column">
diff --git a/app/server-control/controllers/power-operations-controller.html b/app/server-control/controllers/power-operations-controller.html
index 5587ecd..5cfdec1 100644
--- a/app/server-control/controllers/power-operations-controller.html
+++ b/app/server-control/controllers/power-operations-controller.html
@@ -4,7 +4,7 @@
<h1>Server power operations</h1>
<div class="power__current-status page-header">
<h2 class="inline h4">Current status</h2>
- <div class="power__status-log inline float-right">Last power operation at <span class="courier-bold">{{power_time | date:'medium'}}</span></div>
+ <div class="power__status-log inline float-right">Last power operation at <span class="courier-bold">{{power_time | localeDate}}</span></div>
</div>
</div>
<div class="row column">
diff --git a/app/server-health/controllers/log-controller.html b/app/server-health/controllers/log-controller.html
index 7aadc11..f3f9e89 100644
--- a/app/server-health/controllers/log-controller.html
+++ b/app/server-health/controllers/log-controller.html
@@ -8,11 +8,11 @@
<h2 class="inline h4">All events from the BMC</h2>
<div class="event-log__timezone inline float-right">
<button class="dropdown__button" ng-click="timezone = timezone == true ? false : true;" toggle-flag="timezone">
- <span>{{tmz === 'UTC'? 'UTC Timezone' : 'User Timezone'}}</span>
+ <span>{{tmz === 'UTC' ? 'UTC Timezone' : 'User Timezone'}}</span>
</button>
<ul class="dropdown__list inline" ng-show="timezone">
<li>
- <button ng-click="selectUserTimezone();">User Timezone</button>
+ <button ng-click="tmz = ''">User Timezone</button>
</li>
<li>
<button ng-click="tmz = 'UTC'">UTC Timezone</button>
diff --git a/app/server-health/controllers/log-controller.js b/app/server-health/controllers/log-controller.js
index 0303854..a604126 100644
--- a/app/server-health/controllers/log-controller.js
+++ b/app/server-health/controllers/log-controller.js
@@ -69,7 +69,6 @@
dataService.updateServerHealth(result.data);
$scope.logs = result.data;
$scope.originalData = result.original;
- $scope.selectUserTimezone();
$scope.loading = false;
});
};
@@ -102,9 +101,9 @@
}
if ($scope.start_date && endDate) {
- var date = new Date($filter('date')(
- log.Timestamp, 'MM/dd/yyyy HH:mm:ss', $scope.tmz));
- return (date >= $scope.start_date && date <= endDate);
+ return (
+ log.Timestamp >= $scope.start_date &&
+ log.Timestamp <= endDate);
} else {
return true;
}
@@ -160,10 +159,6 @@
$scope.export_data = JSON.stringify(data);
}
- $scope.selectUserTimezone = function() {
- $scope.tmz = new Date().toString().match(/\(([A-Za-z\s].*)\)/)[1];
- };
-
$scope.accept = function() {
APIUtils.deleteLogs($scope.selectedEvents).then(function() {
$scope.confirm = false;