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/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;
       }