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;