]> source.dussan.org Git - nextcloud-server.git/commitdiff
Etc timezones don't exist for .5 and .75 offsets
authorJoas Schilling <nickvergessen@gmx.de>
Mon, 23 Feb 2015 11:33:15 +0000 (12:33 +0100)
committerJoas Schilling <nickvergessen@owncloud.com>
Tue, 3 Mar 2015 08:08:47 +0000 (09:08 +0100)
lib/private/datetimezone.php
tests/lib/util.php

index e4a0af4fc69e81dd0945ef15300eb39613cfc50d..727ce321dba17c6fc1bf0e94ddaca6afee4388d3 100644 (file)
@@ -44,19 +44,66 @@ class DateTimeZone implements IDateTimeZone {
                $timeZone = $this->config->getUserValue($this->session->get('user_id'), 'core', 'timezone', null);
                if ($timeZone === null) {
                        if ($this->session->exists('timezone')) {
-                               $offsetHours = $this->session->get('timezone');
-                               // Note: the timeZone name is the inverse to the offset,
-                               // so a positive offset means negative timeZone
-                               // and the other way around.
-                               if ($offsetHours > 0) {
-                                       return new \DateTimeZone('Etc/GMT-' . $offsetHours);
-                               } else {
-                                       return new \DateTimeZone('Etc/GMT+' . abs($offsetHours));
-                               }
+                               return $this->guessTimeZoneFromOffset($this->session->get('timezone'));
+                       }
+                       $timeZone = $this->getDefaultTimeZone();
+               }
+
+               try {
+                       return new \DateTimeZone($timeZone);
+               } catch (\Exception $e) {
+                       \OCP\Util::writeLog('datetimezone', 'Failed to created DateTimeZone "' . $timeZone . "'", \OCP\Util::DEBUG);
+                       return new \DateTimeZone($this->getDefaultTimeZone());
+               }
+       }
+
+       /**
+        * Guess the DateTimeZone for a given offset
+        *
+        * We first try to find a Etc/GMT* timezone, if that does not exist,
+        * we try to find it manually, before falling back to UTC.
+        *
+        * @param mixed $offset
+        * @return \DateTimeZone
+        */
+       protected function guessTimeZoneFromOffset($offset) {
+               try {
+                       // Note: the timeZone name is the inverse to the offset,
+                       // so a positive offset means negative timeZone
+                       // and the other way around.
+                       if ($offset > 0) {
+                               $timeZone = 'Etc/GMT-' . $offset;
                        } else {
-                               return new \DateTimeZone('UTC');
+                               $timeZone = 'Etc/GMT+' . abs($offset);
                        }
+
+                       return new \DateTimeZone($timeZone);
+               } catch (\Exception $e) {
+                       // If the offset has no Etc/GMT* timezone,
+                       // we try to guess one timezone that has the same offset
+                       foreach (\DateTimeZone::listIdentifiers() as $timeZone) {
+                               $dtz = new \DateTimeZone($timeZone);
+                               $dtOffset = $dtz->getOffset(new \DateTime());
+                               if ($dtOffset == 3600 * $offset) {
+                                       return $dtz;
+                               }
+                       }
+
+                       // No timezone found, fallback to UTC
+                       \OCP\Util::writeLog('datetimezone', 'Failed to find DateTimeZone for offset "' . $offset . "'", \OCP\Util::DEBUG);
+                       return new \DateTimeZone($this->getDefaultTimeZone());
                }
-               return new \DateTimeZone($timeZone);
+       }
+
+       /**
+        * Get the default timezone of the server
+        *
+        * Falls back to UTC if it is not yet set.
+        * 
+        * @return string
+        */
+       protected function getDefaultTimeZone() {
+               $serverTimeZone = date_default_timezone_get();
+               return $serverTimeZone ?: 'UTC';
        }
 }
index 6870b218076cfe4fd6b1cc997c8854abb9335e01..a852eee8ad61c94d3c425d974911e644462d1c33 100644 (file)
@@ -52,16 +52,31 @@ class Test_Util extends \Test\TestCase {
                OC_Util::formatDate(1350129205, false, 'Mordor/Barad-dûr');
        }
 
-       function testFormatDateWithTZFromSession() {
+       public function formatDateWithTZFromSessionData()
+       {
+               return array(
+                       array(3, 'October 13, 2012 at 2:53:25 PM GMT+3'),
+                       array(15, 'October 13, 2012 at 11:53:25 AM GMT+0'),
+                       array(-13, 'October 13, 2012 at 11:53:25 AM GMT+0'),
+                       array(3.5, 'October 13, 2012 at 3:23:25 PM GMT+3:30'),
+                       array(9.5, 'October 13, 2012 at 9:23:25 PM GMT+9:30'),
+                       array(-4.5, 'October 13, 2012 at 7:23:25 AM GMT-4:30'),
+                       array(15.5, 'October 13, 2012 at 11:53:25 AM GMT+0'),
+               );
+       }
+
+       /**
+        * @dataProvider formatDateWithTZFromSessionData
+        */
+       function testFormatDateWithTZFromSession($offset, $expected) {
                date_default_timezone_set("UTC");
 
                $oldDateTimeFormatter = \OC::$server->query('DateTimeFormatter');
-               \OC::$server->getSession()->set('timezone', 3);
+               \OC::$server->getSession()->set('timezone', $offset);
                $newDateTimeFormatter = new \OC\DateTimeFormatter(\OC::$server->getDateTimeZone()->getTimeZone(), new \OC_L10N('lib', 'en'));
                $this->setDateFormatter($newDateTimeFormatter);
 
                $result = OC_Util::formatDate(1350129205, false);
-               $expected = 'October 13, 2012 at 2:53:25 PM GMT+3';
                $this->assertEquals($expected, $result);
 
                $this->setDateFormatter($oldDateTimeFormatter);