Forráskód Böngészése

Migrate from timezone offsets to PHP timezone identifiers

Visman 2 éve
szülő
commit
f1bc7954ef

+ 2 - 4
app/Models/Pages/Admin/Install.php

@@ -1095,8 +1095,7 @@ class Install extends Admin
                 'show_img_sig'     => ['TINYINT(1)', false, 1],
                 'show_avatars'     => ['TINYINT(1)', false, 1],
                 'show_sig'         => ['TINYINT(1)', false, 1],
-                'timezone'         => ['FLOAT', false, 0],
-                'dst'              => ['TINYINT(1)', false, 0],
+                'timezone'         => ['VARCHAR(255)', false, \date_default_timezone_get()],
                 'time_format'      => ['TINYINT(1)', false, 0],
                 'date_format'      => ['TINYINT(1)', false, 0],
                 'language'         => ['VARCHAR(25)', false, ''],
@@ -1378,7 +1377,7 @@ class Install extends Admin
             'i_fork_revision'         => $this->c->FORK_REVISION,
             'o_board_title'           => $v->title,
             'o_board_desc'            => $v->descr,
-            'o_default_timezone'      => 0,
+            'o_default_timezone'      => \date_default_timezone_get(),
             'i_timeout_visit'         => 3600,
             'i_timeout_online'        => 900,
             'i_redirect_delay'        => 1,
@@ -1426,7 +1425,6 @@ class Install extends Admin
             'o_rules_message'         => __('Rules '),
             'b_maintenance'           => 0,
             'o_maintenance_message'   => __('Maintenance message '),
-            'b_default_dst'           => 0,
             'i_feed_type'             => 2,
             'i_feed_ttl'              => 0,
             'b_message_bbcode'        => 1,

+ 6 - 53
app/Models/Pages/Admin/Options.php

@@ -13,11 +13,15 @@ namespace ForkBB\Models\Pages\Admin;
 use ForkBB\Core\Validator;
 use ForkBB\Models\Page;
 use ForkBB\Models\Pages\Admin;
+use ForkBB\Models\Pages\TimeZoneTrait;
 use ForkBB\Models\Config\Config;
+use DateTimeZone;
 use function \ForkBB\__;
 
 class Options extends Admin
 {
+    use TimeZoneTrait;
+
     /**
      * Редактирование натроек форума
      */
@@ -39,8 +43,7 @@ class Options extends Admin
                     'token'                   => 'token:AdminOptions',
                     'o_board_title'           => 'required|string:trim|max:255',
                     'o_board_desc'            => 'exist|string:trim,empty|max:65000 bytes|html',
-                    'o_default_timezone'      => 'required|string:trim|in:-12,-11,-10,-9.5,-9,-8.5,-8,-7,-6,-5,-4,-3.5,-3,-2,-1,0,1,2,3,3.5,4,4.5,5,5.5,5.75,6,6.5,7,8,8.75,9,9.5,10,10.5,11,11.5,12,12.75,13,14',
-                    'b_default_dst'           => 'required|integer|in:0,1',
+                    'o_default_timezone'      => 'required|string:trim|in:' . \implode(',', DateTimeZone::listIdentifiers()),
                     'o_default_lang'          => 'required|string:trim|in:' . \implode(',', $this->c->Func->getLangs()),
                     'o_default_style'         => 'required|string:trim|in:' . \implode(',', $this->c->Func->getStyles()),
                     'i_timeout_visit'         => 'required|integer|min:0|max:99999',
@@ -219,59 +222,11 @@ class Options extends Admin
                 ],
                 'o_default_timezone' => [
                     'type'    => 'select',
-                    'options' => [
-                        '-12'   => __('UTC-12:00'),
-                        '-11'   => __('UTC-11:00'),
-                        '-10'   => __('UTC-10:00'),
-                        '-9.5'  => __('UTC-09:30'),
-                        '-9'    => __('UTC-09:00'),
-                        '-8.5'  => __('UTC-08:30'),
-                        '-8'    => __('UTC-08:00'),
-                        '-7'    => __('UTC-07:00'),
-                        '-6'    => __('UTC-06:00'),
-                        '-5'    => __('UTC-05:00'),
-                        '-4'    => __('UTC-04:00'),
-                        '-3.5'  => __('UTC-03:30'),
-                        '-3'    => __('UTC-03:00'),
-                        '-2'    => __('UTC-02:00'),
-                        '-1'    => __('UTC-01:00'),
-                        '0'     => __('UTC'),
-                        '1'     => __('UTC+01:00'),
-                        '2'     => __('UTC+02:00'),
-                        '3'     => __('UTC+03:00'),
-                        '3.5'   => __('UTC+03:30'),
-                        '4'     => __('UTC+04:00'),
-                        '4.5'   => __('UTC+04:30'),
-                        '5'     => __('UTC+05:00'),
-                        '5.5'   => __('UTC+05:30'),
-                        '5.75'  => __('UTC+05:45'),
-                        '6'     => __('UTC+06:00'),
-                        '6.5'   => __('UTC+06:30'),
-                        '7'     => __('UTC+07:00'),
-                        '8'     => __('UTC+08:00'),
-                        '8.75'  => __('UTC+08:45'),
-                        '9'     => __('UTC+09:00'),
-                        '9.5'   => __('UTC+09:30'),
-                        '10'    => __('UTC+10:00'),
-                        '10.5'  => __('UTC+10:30'),
-                        '11'    => __('UTC+11:00'),
-                        '11.5'  => __('UTC+11:30'),
-                        '12'    => __('UTC+12:00'),
-                        '12.75' => __('UTC+12:45'),
-                        '13'    => __('UTC+13:00'),
-                        '14'    => __('UTC+14:00'),
-                    ],
+                    'options' => $this->createTimeZoneOptions(),
                     'value'   => $config->o_default_timezone,
                     'caption' => 'Timezone label',
                     'help'    => 'Timezone help',
                 ],
-                'b_default_dst' => [
-                    'type'    => 'radio',
-                    'value'   => $config->b_default_dst,
-                    'values'  => $yn,
-                    'caption' => 'DST label',
-                    'help'    => 'DST help',
-                ],
                 'o_default_lang' => [
                     'type'    => 'select',
                     'options' => $langs,
@@ -289,8 +244,6 @@ class Options extends Admin
             ],
         ];
 
-        $timestamp = \time() + ($this->user->timezone + $this->user->dst) * 3600;
-
         $form['sets']['timeouts'] = [
             'legend' => 'Timeouts subhead',
             'fields' => [

+ 20 - 1
app/Models/Pages/Admin/Update.php

@@ -25,7 +25,7 @@ class Update extends Admin
 {
     const PHP_MIN                    = '7.3.0';
     const REV_MIN_FOR_UPDATE         = 42;
-    const LATEST_REV_WITH_DB_CHANGES = 52;
+    const LATEST_REV_WITH_DB_CHANGES = 53;
     const LOCK_NAME                  = 'lock_update';
     const LOCk_TTL                   = 1800;
     const JSON_OPTIONS               = \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE | \JSON_THROW_ON_ERROR;
@@ -803,4 +803,23 @@ class Update extends Admin
 
         return null;
     }
+
+    /**
+     * rev.52 to rev.53
+     */
+    protected function stageNumber52(array $args): ?int
+    {
+        $this->c->DB->dropField('::users', 'dst');
+        $this->c->DB->alterField('::users', 'timezone', 'VARCHAR(255)', false, \date_default_timezone_get());
+
+        $config = $this->c->config;
+
+        $config->o_default_timezone = \date_default_timezone_get();
+
+        unset($config->b_default_dst);
+
+        $config->save();
+
+        return null;
+    }
 }

+ 0 - 1
app/Models/Pages/Admin/Users/NewUser.php

@@ -56,7 +56,6 @@ class NewUser extends Users
                     $user->u_mark_all_read = \time();
                     $user->email_setting   = $this->c->config->i_default_email_setting;
                     $user->timezone        = $this->c->config->o_default_timezone;
-                    $user->dst             = $this->c->config->b_default_dst;
                     $user->language        = $this->c->config->o_default_lang;
                     $user->style           = $this->c->config->o_default_style;
                     $user->registered      = \time();

+ 6 - 52
app/Models/Pages/Profile/Config.php

@@ -13,11 +13,15 @@ namespace ForkBB\Models\Pages\Profile;
 use ForkBB\Core\Validator;
 use ForkBB\Models\Page;
 use ForkBB\Models\Pages\Profile;
+use ForkBB\Models\Pages\TimeZoneTrait;
+use DateTimeZone;
 use function \ForkBB\__;
 use function \ForkBB\dt;
 
 class Config extends Profile
 {
+    use TimeZoneTrait;
+
     /**
      * Подготавливает данные для шаблона настройки форума
      */
@@ -41,8 +45,7 @@ class Config extends Profile
                     'token'         => 'token:EditUserBoardConfig',
                     'language'      => 'required|string:trim|in:' . \implode(',', $this->c->Func->getLangs()),
                     'style'         => 'required|string:trim|in:' . \implode(',', $this->c->Func->getStyles()),
-                    'timezone'      => 'required|numeric|in:-12,-11,-10,-9.5,-9,-8.5,-8,-7,-6,-5,-4,-3.5,-3,-2,-1,0,1,2,3,3.5,4,4.5,5,5.5,5.75,6,6.5,7,8,8.75,9,9.5,10,10.5,11,11.5,12,12.75,13,14',
-                    'dst'           => 'required|integer|in:0,1',
+                    'timezone'      => 'required|string|in:' . \implode(',', DateTimeZone::listIdentifiers()),
                     'time_format'   => 'required|integer|in:' . \implode(',', \array_keys($this->c->TIME_FORMATS)),
                     'date_format'   => 'required|integer|in:' . \implode(',', \array_keys($this->c->DATE_FORMATS)),
                     'show_smilies'  => 'required|integer|in:0,1',
@@ -62,7 +65,6 @@ class Config extends Profile
                     'language'      => 'Language',
                     'style'         => 'Style',
                     'timezone'      => 'Time zone',
-                    'dst'           => 'DST label',
                     'time_format'   => 'Time format',
                     'date_format'   => 'Date format',
                     'show_smilies'  => 'Smilies label',
@@ -186,58 +188,10 @@ class Config extends Profile
                 ],
                 'timezone' => [
                     'type'    => 'select',
-                    'options' => [
-                        '-12'   => __('UTC-12:00'),
-                        '-11'   => __('UTC-11:00'),
-                        '-10'   => __('UTC-10:00'),
-                        '-9.5'  => __('UTC-09:30'),
-                        '-9'    => __('UTC-09:00'),
-                        '-8.5'  => __('UTC-08:30'),
-                        '-8'    => __('UTC-08:00'),
-                        '-7'    => __('UTC-07:00'),
-                        '-6'    => __('UTC-06:00'),
-                        '-5'    => __('UTC-05:00'),
-                        '-4'    => __('UTC-04:00'),
-                        '-3.5'  => __('UTC-03:30'),
-                        '-3'    => __('UTC-03:00'),
-                        '-2'    => __('UTC-02:00'),
-                        '-1'    => __('UTC-01:00'),
-                        '0'     => __('UTC'),
-                        '1'     => __('UTC+01:00'),
-                        '2'     => __('UTC+02:00'),
-                        '3'     => __('UTC+03:00'),
-                        '3.5'   => __('UTC+03:30'),
-                        '4'     => __('UTC+04:00'),
-                        '4.5'   => __('UTC+04:30'),
-                        '5'     => __('UTC+05:00'),
-                        '5.5'   => __('UTC+05:30'),
-                        '5.75'  => __('UTC+05:45'),
-                        '6'     => __('UTC+06:00'),
-                        '6.5'   => __('UTC+06:30'),
-                        '7'     => __('UTC+07:00'),
-                        '8'     => __('UTC+08:00'),
-                        '8.75'  => __('UTC+08:45'),
-                        '9'     => __('UTC+09:00'),
-                        '9.5'   => __('UTC+09:30'),
-                        '10'    => __('UTC+10:00'),
-                        '10.5'  => __('UTC+10:30'),
-                        '11'    => __('UTC+11:00'),
-                        '11.5'  => __('UTC+11:30'),
-                        '12'    => __('UTC+12:00'),
-                        '12.75' => __('UTC+12:45'),
-                        '13'    => __('UTC+13:00'),
-                        '14'    => __('UTC+14:00'),
-                    ],
+                    'options' => $this->createTimeZoneOptions(),
                     'value'   => $this->curUser->timezone,
                     'caption' => 'Time zone',
                 ],
-                'dst' => [
-                    'type'    => 'radio',
-                    'value'   => $this->curUser->dst,
-                    'values'  => $yn,
-                    'caption' => 'DST label',
-                    'help'    => 'DST help',
-                ],
                 'time_format' => [
                     'type'    => 'select',
                     'options' => $timeFormat,

+ 0 - 1
app/Models/Pages/Register.php

@@ -169,7 +169,6 @@ class Register extends Page
         $user->u_mark_all_read = \time();
         $user->email_setting   = $this->c->config->i_default_email_setting;
         $user->timezone        = $this->c->config->o_default_timezone;
-        $user->dst             = $this->c->config->b_default_dst;
         $user->language        = $this->user->language;
         $user->style           = $this->user->style;
         $user->registered      = \time();

+ 60 - 0
app/Models/Pages/TimeZoneTrait.php

@@ -0,0 +1,60 @@
+<?php
+/**
+ * This file is part of the ForkBB <https://github.com/forkbb>.
+ *
+ * @copyright (c) Visman <mio.visman@yandex.ru, https://github.com/MioVisman>
+ * @license   The MIT License (MIT)
+ */
+
+declare(strict_types=1);
+
+namespace ForkBB\Models\Pages;
+
+use DateTime;
+use DateTimeZone;
+use IntlDateFormatter;
+use function \ForkBB\__;
+
+trait TimeZoneTrait
+{
+    protected function createTimeZoneOptions() : array
+    {
+        $list = [];
+
+        foreach (DateTimeZone::listIdentifiers() as $zone) {
+            $dateTimeZone          = new DateTimeZone($zone);
+            $dateTime              = new DateTime('now', $dateTimeZone);
+            $offset                = $dateTime->getOffset();
+            $list[$offset][$zone]  = $zone;
+        }
+
+        \ksort($list, \SORT_NUMERIC);
+
+        $options = [];
+        $now     = \time();
+
+        foreach ($list as $offset => $group) {
+            $hm    = $this->offsetToHM($offset);
+            $first = true;
+
+            \asort($group, \SORT_STRING);
+
+            foreach ($group as $zone => $value) {
+                if ($first) {
+                    $first     = false;
+                    $format    = new IntlDateFormatter(__('lang_identifier'), IntlDateFormatter::SHORT, IntlDateFormatter::SHORT, $zone);
+                    $options[] = ['(UTC' . $hm . ') ' . $format->format($now)];
+                }
+
+                $options[] = [$zone, $value];
+            }
+        }
+
+        return $options;
+    }
+
+    protected function offsetToHM(int $offset) : string
+    {
+        return $offset < 0 ? '-' . \gmdate('H:i', -$offset) : '+' . \gmdate('H:i', $offset);
+    }
+}

+ 0 - 1
app/Models/User/Current.php

@@ -46,7 +46,6 @@ class Current extends Action
         if ($user->isGuest) {
             $user->__isBot    = $this->isBot($user->userAgent);
             $user->__timezone = $this->c->config->o_default_timezone;
-            $user->__dst      = $this->c->config->b_default_dst;
             $user->__language = $this->getLangFromHTTP();
         } else {
             $user->__isBot = false;

+ 1 - 1
app/bootstrap.php

@@ -58,7 +58,7 @@ if (
     $c->BASE_URL = \str_replace('https://', 'http://', $c->BASE_URL);
 }
 
-$c->FORK_REVISION = 52;
+$c->FORK_REVISION = 53;
 $c->START         = $forkStart;
 $c->PUBLIC_URL    = $c->BASE_URL . $forkPublicPrefix;
 

+ 15 - 4
app/functions.php

@@ -11,6 +11,8 @@ declare(strict_types=1);
 namespace ForkBB;
 
 use ForkBB\Core\Container;
+use DateTime;
+use DateTimeZone;
 use InvalidArgumentException;
 
 /**
@@ -91,7 +93,7 @@ function num(/* mixed */ $number, int $decimals = 0): string
  */
 function dt(int $arg, bool $dateOnly = false, string $dateFormat = null, string $timeFormat = null, bool $timeOnly = false, bool $noText = false, Container $container = null): string
 {
-    static $c;
+    static $c, $offset;
 
     if (null !== $container) {
         $c = $container;
@@ -102,8 +104,17 @@ function dt(int $arg, bool $dateOnly = false, string $dateFormat = null, string
         return __('Never');
     }
 
-    $diff = (int) (($c->user->timezone + $c->user->dst) * 3600);
-    $arg += $diff;
+    if (null === $offset) {
+        if (\in_array($c->user->timezone, DateTimeZone::listIdentifiers(), true)) {
+            $dateTimeZone = new DateTimeZone($c->user->timezone);
+            $dateTime     = new DateTime('now', $dateTimeZone);
+            $offset       = $dateTime->getOffset();
+        } else {
+            $offset      = 0;
+        }
+    }
+
+    $arg += $offset;
 
     if (null === $dateFormat) {
         $dateFormat = $c->DATE_FORMATS[$c->user->date_format];
@@ -115,7 +126,7 @@ function dt(int $arg, bool $dateOnly = false, string $dateFormat = null, string
     $date = \gmdate($dateFormat, $arg);
 
     if (! $noText) {
-        $now = \time() + $diff;
+        $now = \time() + $offset;
 
         if ($date == \gmdate($dateFormat, $now)) {
             $date = __('Today');

+ 0 - 6
app/lang/en/profile_other.po

@@ -141,12 +141,6 @@ msgstr "Hide email address but allow form e-mail"
 msgid "Hide both label"
 msgstr "Hide email address and disallow form email"
 
-msgid "DST label"
-msgstr "Adjust for DST"
-
-msgid "DST help"
-msgstr "Check if daylight savings is in effect (advances times by 1 hour)."
-
 msgid "Topics per page label"
 msgstr "Topics per page"
 

+ 0 - 6
app/lang/ru/profile_other.po

@@ -141,12 +141,6 @@ msgstr "Спрятать email, но разрешить отправку пис
 msgid "Hide both label"
 msgstr "Спрятать email и запретить отправку писем"
 
-msgid "DST label"
-msgstr "Поправка на летнее время"
-
-msgid "DST help"
-msgstr "Отметьте, если в вашем регионе применяется поправка на летнее время (сдвигает время на 1 час)."
-
 msgid "Topics per page label"
 msgstr "Тем на странице"