gpt4 book ai didi

php - Laravel/Carbon 中的多时区

转载 作者:可可西里 更新时间:2023-11-01 14:01:50 25 4
gpt4 key购买 nike

我想知道这是否可能,所以假设我有一个这样的模型:

MyModel
SomeDate - Carbon

现在,我也有一个当前用户的时区,如下所示:

User
MyTimezone

数据库中存储的时区始终以 UTC 格式存储(以确保一切一致),输出日期应始终格式化为特定时区(但每个用户的时区不同),例如美国/芝加哥为 User1和 America/Denver 的 User2。

有没有一种方法可以在输出之前自动将每个 Carbon 实例的时区格式化为给定的时区,或者我是否必须循环遍历集合并相应地设置每个时区?

设置 app.timezone 不起作用,因为它还会导致 Carbon 实例以 app.timezone 时区保存到数据库中,而数据库中的所有日期应该是 UTC,因此我失去了一致性。

我目前在 App 配置中将 app.timezone 设置为 UTC,但我也被迫在输出之前将所有 Carbon 实例转换为正确的时区。有没有更好的方法,也许是在 Carbon 变成字符串之前捕获执行并在那里执行?

编辑:

我尝试过的事情:

覆盖 setAttribute 和 getAttribute:

public function setAttribute($property, $value) {
if ($value instanceof Carbon) {
$value->timezone = 'UTC';
}

parent::setAttribute($property, $value);
}

public function getAttribute($key) {
$stuff = parent::getAttribute($key);

if ($stuff instanceof Carbon) {
$stuff->timezone = Helper::fetchUserTimezone();
}

return $stuff;
}

覆盖 asDateTime:

protected function asDateTime($value)
{
// If this value is an integer, we will assume it is a UNIX timestamp's value
// and format a Carbon object from this timestamp. This allows flexibility
// when defining your date fields as they might be UNIX timestamps here.
$timezone = Helper::fetchUserTimezone();

if (is_numeric($value))
{
return Carbon::createFromTimestamp($value, $timezone);
}

// If the value is in simply year, month, day format, we will instantiate the
// Carbon instances from that format. Again, this provides for simple date
// fields on the database, while still supporting Carbonized conversion.
elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $value))
{
return Carbon::createFromFormat('Y-m-d', $value, $timezone)->startOfDay();
}

// Finally, we will just assume this date is in the format used by default on
// the database connection and use that format to create the Carbon object
// that is returned back out to the developers after we convert it here.
elseif ( ! $value instanceof DateTime)
{
$format = $this->getDateFormat();

return Carbon::createFromFormat($format, $value, $timezone);
}

return Carbon::instance($value);
}

最佳答案

我的应用程序遇到了同样的问题,远程网站将以 UTC 格式存储日期,而我必须根据登录用户显示实际日期,我想到了覆盖 Laravel Eloquent 模型。

只需扩展 Illuminate\Database\Eloquent\Model,如下所示:

<?php namespace Vendor\Package;

use Illuminate\Database\Eloquent\Model as EloquentModel;

class Model extends EloquentModel
{

/**
* Return a timestamp as a localized DateTime object.
*
* @param mixed $value
* @return \Carbon\Carbon
*/
protected function asDateTime($value)
{
$carbon = parent::asDateTime($value);
// only make localized if timezone is known
if(Auth::check() && Auth::user()->timezone)
{
$timezone = new DateTimeZone(Auth::user()->timezone);
// mutates the carbon object immediately
$carbon->setTimezone($timezone);
}

return $carbon;
}
/**
* Convert a localized DateTime to a normalized storable string.
*
* @param \DateTime|int $value
* @return string
*/
public function fromDateTime($value)
{
$save = parent::fromDateTime($value);

// only make localized if timezone is known
if(Auth::check() && Auth::user()->timezone)
{
// the format the value is saved to
$format = $this->getDateFormat();

// user timezone
$timezone = new DateTimeZone(Auth::user()->timezone);

$carbon = Carbon::createFromFormat($format, $value, $timezone);
// mutates the carbon object immediately
$carbon->setTimezone(Config::get('app.timezone'));

// now save to format
$save = $carbon->format($format);
}

return $save;
}
}

也许这对其他遇到这个问题的人有用。

作为引用

  • laravel 5 (2015-03-18): Illuminate\Database\Eloquent\Model:2809-2889
  • laravel 4.2 (2015-03-18): Illuminate\Database\Eloquent\Model:2583-2662

关于php - Laravel/Carbon 中的多时区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27792962/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com