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);