使用 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/Makassar
或 Asia/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);
}
我想寻求更好的方法。我将 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/Makassar
或 Asia/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);
}