Laravel 中的 timestampTz 字段
timestampTz fields in Laravel
Laravel 5.4 支持迁移中的 Postgres TIMESTAMP WITH TIME ZONE
字段类型:
$table->timestampTz('scheduled_for');
Laravel 可以设置为将日期字段(DATE
、DATETIME
、TIMESTAMP
)转换为 Carbon 对象(对于 created_at
和 updated_at
TIMESTAMP
字段),但是将 scheduled_for
放入 $dates
字段会导致时区感知版本出错:
InvalidArgumentException with message 'Trailing data'
查看数据库和 tinker,该字段的值似乎类似于 2017-06-19 19:19:19-04
。有没有一种本机方法可以从这些字段类型之一中获取 Carbon 对象?还是我一直在使用访问器?
将其放入您的模型中
protected $casts = [
'scheduled_for' => 'datetime' // date | datetime | timestamp
];
使用 $dates
更有可能过时,因为 $casts
做同样的事情(可能除了 $dateFormat
属性只能用于 $dates
字段 iirc,但我看到有些人对此抱怨)
编辑
我曾在 Laravel 5.4 上测试过 Carbon 并为其创建了一个特征
这还不是生产级代码,因此将其包含在您的模型中需要您自担风险
<?php namespace App\Traits;
use Carbon\Carbon;
trait castTrait
{
protected function castAttribute($key, $value)
{
$database_format = 'Y-m-d H:i:se'; // Store this somewhere in config files
$output_format_date = 'd/m/Y'; // Store this somewhere in config files
$output_format_datetime = 'd/m/Y H:i:s'; // Store this somewhere in config files
if (is_null($value)) {
return $value;
}
switch ($this->getCastType($key)) {
case 'int':
case 'integer':
return (int) $value;
case 'real':
case 'float':
case 'double':
return (float) $value;
case 'string':
return (string) $value;
case 'bool':
case 'boolean':
return (bool) $value;
case 'object':
return $this->fromJson($value, true);
case 'array':
case 'json':
return $this->fromJson($value);
case 'collection':
return new BaseCollection($this->fromJson($value));
case 'date':
Carbon::setToStringFormat($output_format_date);
$date = (string)$this->asDate($value);
Carbon::resetToStringFormat(); // Just for sure
return $date;
case 'datetime':
Carbon::setToStringFormat($output_format_datetime);
$datetime = (string)$this->asDateTime($value);
Carbon::resetToStringFormat();
return $datetime;
case 'timestamp':
return $this->asTimestamp($value);
default:
return $value;
}
}
/**
* Return a timestamp as DateTime object with time set to 00:00:00.
*
* @param mixed $value
* @return \Carbon\Carbon
*/
protected function asDate($value)
{
return $this->asDateTime($value)->startOfDay();
}
/**
* Return a timestamp as DateTime object.
*
* @param mixed $value
* @return \Carbon\Carbon
*/
protected function asDateTime($value)
{
$carbon = null;
$database_format = [ // This variable should also be in config file
'datetime' => 'Y-m-d H:i:se', // e -timezone
'date' => 'Y-m-d'
];
if(empty($value)) {
return null;
}
// If this value is already a Carbon instance, we shall just return it as is.
// This prevents us having to re-instantiate a Carbon instance when we know
// it already is one, which wouldn't be fulfilled by the DateTime check.
if ($value instanceof Carbon) {
$carbon = $value;
}
// If the value is already a DateTime instance, we will just skip the rest of
// these checks since they will be a waste of time, and hinder performance
// when checking the field. We will just return the DateTime right away.
if ($value instanceof DateTimeInterface) {
$carbon = new Carbon(
$value->format($database_format['datetime'], $value->getTimezone())
);
}
// 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.
if (is_numeric($value)) {
$carbon = Carbon::createFromTimestamp($value);
}
// 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.
if ($this->isStandardDateFormat($value)) {
$carbon = Carbon::createFromFormat($database_format['date'], $value)->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.
$carbon = Carbon::createFromFormat(
$database_format['datetime'], $value
);
return $carbon;
}
}
重新提出这个问题,希望有一个有用的答案被接受。
Laravel 采用 Y-m-d H:i:s
数据库时间戳格式。如果您使用的是 Postgres timestampz
列,那显然是不同的。您需要告诉 Eloquent 如何让 Carbon 解析该格式。
只需在您的模型上定义 $dateFormat
属性,如下所示:
Class MyModel extends Eloquent {
protected $dateFormat = 'Y-m-d H:i:sO';
}
归功于应得的功劳:我在 GitHub issue
中找到了这个解决方案
Laravel 5.4 支持迁移中的 Postgres TIMESTAMP WITH TIME ZONE
字段类型:
$table->timestampTz('scheduled_for');
Laravel 可以设置为将日期字段(DATE
、DATETIME
、TIMESTAMP
)转换为 Carbon 对象(对于 created_at
和 updated_at
TIMESTAMP
字段),但是将 scheduled_for
放入 $dates
字段会导致时区感知版本出错:
InvalidArgumentException with message 'Trailing data'
查看数据库和 tinker,该字段的值似乎类似于 2017-06-19 19:19:19-04
。有没有一种本机方法可以从这些字段类型之一中获取 Carbon 对象?还是我一直在使用访问器?
将其放入您的模型中
protected $casts = [
'scheduled_for' => 'datetime' // date | datetime | timestamp
];
使用 $dates
更有可能过时,因为 $casts
做同样的事情(可能除了 $dateFormat
属性只能用于 $dates
字段 iirc,但我看到有些人对此抱怨)
编辑
我曾在 Laravel 5.4 上测试过 Carbon 并为其创建了一个特征
这还不是生产级代码,因此将其包含在您的模型中需要您自担风险
<?php namespace App\Traits;
use Carbon\Carbon;
trait castTrait
{
protected function castAttribute($key, $value)
{
$database_format = 'Y-m-d H:i:se'; // Store this somewhere in config files
$output_format_date = 'd/m/Y'; // Store this somewhere in config files
$output_format_datetime = 'd/m/Y H:i:s'; // Store this somewhere in config files
if (is_null($value)) {
return $value;
}
switch ($this->getCastType($key)) {
case 'int':
case 'integer':
return (int) $value;
case 'real':
case 'float':
case 'double':
return (float) $value;
case 'string':
return (string) $value;
case 'bool':
case 'boolean':
return (bool) $value;
case 'object':
return $this->fromJson($value, true);
case 'array':
case 'json':
return $this->fromJson($value);
case 'collection':
return new BaseCollection($this->fromJson($value));
case 'date':
Carbon::setToStringFormat($output_format_date);
$date = (string)$this->asDate($value);
Carbon::resetToStringFormat(); // Just for sure
return $date;
case 'datetime':
Carbon::setToStringFormat($output_format_datetime);
$datetime = (string)$this->asDateTime($value);
Carbon::resetToStringFormat();
return $datetime;
case 'timestamp':
return $this->asTimestamp($value);
default:
return $value;
}
}
/**
* Return a timestamp as DateTime object with time set to 00:00:00.
*
* @param mixed $value
* @return \Carbon\Carbon
*/
protected function asDate($value)
{
return $this->asDateTime($value)->startOfDay();
}
/**
* Return a timestamp as DateTime object.
*
* @param mixed $value
* @return \Carbon\Carbon
*/
protected function asDateTime($value)
{
$carbon = null;
$database_format = [ // This variable should also be in config file
'datetime' => 'Y-m-d H:i:se', // e -timezone
'date' => 'Y-m-d'
];
if(empty($value)) {
return null;
}
// If this value is already a Carbon instance, we shall just return it as is.
// This prevents us having to re-instantiate a Carbon instance when we know
// it already is one, which wouldn't be fulfilled by the DateTime check.
if ($value instanceof Carbon) {
$carbon = $value;
}
// If the value is already a DateTime instance, we will just skip the rest of
// these checks since they will be a waste of time, and hinder performance
// when checking the field. We will just return the DateTime right away.
if ($value instanceof DateTimeInterface) {
$carbon = new Carbon(
$value->format($database_format['datetime'], $value->getTimezone())
);
}
// 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.
if (is_numeric($value)) {
$carbon = Carbon::createFromTimestamp($value);
}
// 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.
if ($this->isStandardDateFormat($value)) {
$carbon = Carbon::createFromFormat($database_format['date'], $value)->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.
$carbon = Carbon::createFromFormat(
$database_format['datetime'], $value
);
return $carbon;
}
}
重新提出这个问题,希望有一个有用的答案被接受。
Laravel 采用 Y-m-d H:i:s
数据库时间戳格式。如果您使用的是 Postgres timestampz
列,那显然是不同的。您需要告诉 Eloquent 如何让 Carbon 解析该格式。
只需在您的模型上定义 $dateFormat
属性,如下所示:
Class MyModel extends Eloquent {
protected $dateFormat = 'Y-m-d H:i:sO';
}
归功于应得的功劳:我在 GitHub issue
中找到了这个解决方案