Laravel将timestamp转为date:Y/n/j格式时显示错误如何解决
Laravel日期cast格式转换偏差问题解答
问题原因
Laravel 7+ 版本默认对日期字段做JSON序列化时,会统一转换为UTC时区输出,不受config/app.php中timezone配置的影响。你配置的date:Y/n/j格式转换是在序列化阶段执行的,因此会基于转换后的UTC时间做日期格式化:
- 你数据库中存储的
2021-06-08 01:00:01为东九区(Asia/Tokyo)时间,转换为UTC时间后为2021-06-07 16:00:01,格式化日期就得到2021/6/7 - 当存储的时间大于等于东九区
2021-06-08 09:00:00时,转换为UTC时间后为2021-06-08 00:00:00,格式化日期就得到预期的2021/6/8,和你观察到的现象完全吻合。
解决方案
方案1:全局配置序列化使用应用时区(推荐)
Laravel 8.49.0及以上版本可直接在.env文件中添加以下配置,让日期序列化自动使用你配置的Asia/Tokyo时区:
SERIALIZE_DATES_USING_TIMEZONE=true
配置完成后执行php artisan config:cache清除配置缓存即可生效。
如果你的Laravel 8小版本低于8.49.0,可在app/Providers/AppServiceProvider.php的boot方法中添加以下代码实现相同效果:
use Illuminate\Support\Carbon; public function boot() { Carbon::serializeUsing(function ($carbon) { return $carbon->toIso8601String(); }); }
方案2:单独调整该字段的转换逻辑
如果不想修改全局序列化规则,只需要调整created_at字段的输出格式,可以将模型中的casts配置替换为自定义访问器:
class Diary extends Model { // 移除原有created_at的casts配置 public function getCreatedAtAttribute($value) { return \Carbon\Carbon::parse($value)->timezone(config('app.timezone'))->format('Y/n/j'); } }
可选补充:对齐数据库连接时区
为了避免后续读写时间出现其他时区偏差,建议在config/database.php的MySQL配置项中添加时区配置,和应用时区保持一致:
'mysql' => [ // 其他原有配置保持不变 'timezone' => '+09:00', ],
内容的提问来源于stack exchange,提问作者Ricardinho
相关产品推荐
相关产品推荐

