You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
3.6 KiB

3 years ago
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. * @author Joas Schilling <coding@schilljs.com>
  8. * @author Morris Jobke <hey@morrisjobke.de>
  9. *
  10. * @license AGPL-3.0
  11. *
  12. * This code is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Affero General Public License, version 3,
  14. * as published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU Affero General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Affero General Public License, version 3,
  22. * along with this program. If not, see <http://www.gnu.org/licenses/>
  23. *
  24. */
  25. namespace OC;
  26. use OCP\IConfig;
  27. use OCP\IDateTimeZone;
  28. use OCP\ILogger;
  29. use OCP\ISession;
  30. class DateTimeZone implements IDateTimeZone {
  31. /** @var IConfig */
  32. protected $config;
  33. /** @var ISession */
  34. protected $session;
  35. /**
  36. * Constructor
  37. *
  38. * @param IConfig $config
  39. * @param ISession $session
  40. */
  41. public function __construct(IConfig $config, ISession $session) {
  42. $this->config = $config;
  43. $this->session = $session;
  44. }
  45. /**
  46. * Get the timezone of the current user, based on his session information and config data
  47. *
  48. * @param bool|int $timestamp
  49. * @return \DateTimeZone
  50. */
  51. public function getTimeZone($timestamp = false) {
  52. $timeZone = $this->config->getUserValue($this->session->get('user_id'), 'core', 'timezone', null);
  53. if ($timeZone === null) {
  54. if ($this->session->exists('timezone')) {
  55. return $this->guessTimeZoneFromOffset($this->session->get('timezone'), $timestamp);
  56. }
  57. $timeZone = $this->getDefaultTimeZone();
  58. }
  59. try {
  60. return new \DateTimeZone($timeZone);
  61. } catch (\Exception $e) {
  62. \OCP\Util::writeLog('datetimezone', 'Failed to created DateTimeZone "' . $timeZone . "'", ILogger::DEBUG);
  63. return new \DateTimeZone($this->getDefaultTimeZone());
  64. }
  65. }
  66. /**
  67. * Guess the DateTimeZone for a given offset
  68. *
  69. * We first try to find a Etc/GMT* timezone, if that does not exist,
  70. * we try to find it manually, before falling back to UTC.
  71. *
  72. * @param mixed $offset
  73. * @param bool|int $timestamp
  74. * @return \DateTimeZone
  75. */
  76. protected function guessTimeZoneFromOffset($offset, $timestamp) {
  77. try {
  78. // Note: the timeZone name is the inverse to the offset,
  79. // so a positive offset means negative timeZone
  80. // and the other way around.
  81. if ($offset > 0) {
  82. $timeZone = 'Etc/GMT-' . $offset;
  83. } else {
  84. $timeZone = 'Etc/GMT+' . abs($offset);
  85. }
  86. return new \DateTimeZone($timeZone);
  87. } catch (\Exception $e) {
  88. // If the offset has no Etc/GMT* timezone,
  89. // we try to guess one timezone that has the same offset
  90. foreach (\DateTimeZone::listIdentifiers() as $timeZone) {
  91. $dtz = new \DateTimeZone($timeZone);
  92. $dateTime = new \DateTime();
  93. if ($timestamp !== false) {
  94. $dateTime->setTimestamp($timestamp);
  95. }
  96. $dtOffset = $dtz->getOffset($dateTime);
  97. if ($dtOffset == 3600 * $offset) {
  98. return $dtz;
  99. }
  100. }
  101. // No timezone found, fallback to UTC
  102. \OCP\Util::writeLog('datetimezone', 'Failed to find DateTimeZone for offset "' . $offset . "'", ILogger::DEBUG);
  103. return new \DateTimeZone($this->getDefaultTimeZone());
  104. }
  105. }
  106. /**
  107. * Get the default timezone of the server
  108. *
  109. * Falls back to UTC if it is not yet set.
  110. *
  111. * @return string
  112. */
  113. protected function getDefaultTimeZone() {
  114. $serverTimeZone = date_default_timezone_get();
  115. return $serverTimeZone ?: 'UTC';
  116. }
  117. }