使用 PostgreSQL 在 Yii2 上的用户时区问题

Users' timezone issue onYii2 with PostgreSQL

我想寻求更好的方法。我将 Yii2 与 PostgreSQL 一起使用,并将所有 table 的所有时间戳字段设置为 timestamp with timezone 数据类型。

timestamp with time zone NOT NULL DEFAULT now()

我已经创建了每次响应都会调用的设置,

Yii::$app->setTimezone(MallSettings::getSetting('timezone', Yii::$app->session['mall_id']));

这将 return 类似 Asia/MakassarAsia/Jakarta 的东西(这取决于用户的设置)。

我扩展了 \yiin\Formatter,使用下面名为 ZeedFormatter 的 class,并创建了一个新函数来显示用户首选时区的日期时间值。

class ZeedFormatter extends \yii\i18n\Formatter
{
    /**
     * Format timestamp with timezone value to user's preferred timezone.
     * (extends the asDatetime() functionality)
     * 
     * @param  [type] $value  [description]
     * @param  [type] $format [description]
     * @return [type]         [description]
     */
    public function asLocaldatetime($value, $format = null)
    {
        $originalDateTime = \DateTime::createFromFormat('Y-m-d H:i:s.uO', $value);
        $originalDateTime->setTimezone(new \DateTimeZone(date_default_timezone_get()));

        if ($format === null)
            $format = 'Y-m-d H:i:s.uO';

        $localDateTime = $originalDateTime->format($format);

        return $localDateTime;

    }
}

我的想法是,每当我需要 'local' 日期时间格式时,我都可以这样调用它:

    Yii::$app->formatter->asLocaldatetime('2019-08-29 19:52:21.02886+07');
    // will return 2019-08-29 20:52:21.02886+08 for Asia/Makassar timezone

或者,如果在 GridView 中使用,


       'position',
       'created_at:localdatetime',

       ['class' => 'backend\widgets\ActionColumn'],

我可以只使用 Yii2 的特性来获得这个功能吗?或者(另一个选项)从 Psql 查询调用 created_at AT TIME ZONE 'Asia/Makassar'?希望能得到启示。谢谢。

我的(另一种)方法是继续使用 asDatetime() 函数。

我刚刚意识到我需要从配置文件中删除/注释 timezone。如果值在那里设置,无论我如何在其他地方设置时区,如果我们使用 asDatetime 格式化程序,Yii 总是从配置文件 (common/config/main.php) 中获取值。

    'components' => [
        'formatter' => [
            // 'class' => '\common\modules\ZeedFormatter',
            'locale' => 'id-ID',
            // 'timeZone' => 'Asia/Jakarta',
            'defaultTimeZone' => 'Asia/Jakarta',
            'dateFormat' => 'php:j M Y',
            'decimalSeparator' => ',',
            'thousandSeparator' => '.',
            'currencyCode' => 'Rp ',
            'nullDisplay' => '<em style="color:#d8d8d8">null</em>',
            'numberFormatterOptions' => [
                NumberFormatter::MIN_FRACTION_DIGITS => 0,
                NumberFormatter::MAX_FRACTION_DIGITS => 0,
            ],
        ],
    ]

如果我们需要另一种(或定制的)格式,我们仍然可以使用上面的 ZeedFormatter 并添加一些所需的功能。例如:

    public function asMyformat($value)
    {
        $timestamp = strtotime($value);
        $fmt = new \IntlDateFormatter('id-ID', \IntlDateFormatter::NONE, \IntlDateFormatter::LONG);

        $fmt->setPattern('hh:mm z');// will return something like '09:47 WITA' 

        return $fmt->format($timestamp);
    }