【问题标题】:Laravel Carbon does not consider timezone DSTLaravel Carbon 不考虑时区夏令时
【发布时间】:2017-09-15 01:33:44
【问题描述】:

鉴于我的 UsersTableSeeder.php 课程,我正在使用循环在我的数据库中植入假数据:

$numberOfUsers = 150;

DB::table('users')->delete();

$faker = Faker::create();

for ($i = 1; $i <= $numberOfUsers; $i++) {
    DB::table('users')->insert([
        'id' => $i,
        'firstName' => $faker->firstName,
        'lastName' => $faker->lastName,
        'email' => $faker->email,
        'password' => bcrypt("123"),
        'created_at' => Carbon::now()->addDays((-5 * $i) - 2)->format('Y-m-d H:i:s'),
        'updated_at' => Carbon::now()->addDays(-5 * $i)->format('Y-m-d H:i:s'),
    ]);
}

这里的问题是,当我的日期时间值生成时,它可能会落在 DST 区域中,例如 2017-03-12 02:00:00 和 2017-03-12 02:59:59 之间(确实发生了),它给了我以下错误:

[PDOException]
SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '2016-03-13 02:08:11' for column 'created_at' at row 1

现在我知道我不能在我的数据库中放入这样的值,因为我的数据库足够聪明,可以知道这个时间区域并没有完全退出。但是有什么方法可以让 Carbon 足够聪明地考虑 DST 吗?我不想手动检查它:

if ($my_date > 2017-03-12 02:00:00 && $my_date < 2017-03-12 02:59:59)

【问题讨论】:

  • 你试过Carbon::now('Asia/Tokyo')-&gt;addDays((-5 * $i) - 2)-&gt;format('Y-m-d H:i:s')吗?
  • 为什么需要格式化日期字符串,它应该通过传递碳对象来工作,它将使用的时区是设置中的一个。

标签: php laravel timezone


【解决方案1】:

事实上 Carbon 可以处理 DST 区域。

$date = '2017-03-26 02:01:01';
$date = \Carbon\Carbon::parse($date, 'Europe/Berlin');
dd((string)$date);

结果

// an extra hour was added automatically
"2017-03-26 03:01:01"

默认情况下,Laravel 对所有日期和日期时间操作(包括 Carbon)使用 'UTC'。这个值可以在 app/config.php 中设置

如果您确实希望在数据库中的“UTC”中考虑您的日期时间,那么肮脏的解决方法可能是这样的:

编辑:

// calculate current offset to UTC:
$offset = \Carbon\Carbon::now('America/Montreal')->offsetHours;

'created_at' => Carbon::now('America/Montreal')->addHours(-4 + $i)->addDays((-1 * $i) - 2)->tz('UTC')->addHours($offset)->format('Y-m-d H:i:s')

【讨论】:

  • 如果它处理 DST 区域,为什么它会为 DST 区域生成不存在的时间?我是 UTC-5(加拿大东部)
  • 因为默认默认是UTC,而UTC不知道DST。生成的时间在 UTC 中完全有效,但可能是在其他时区无效的时间
  • 即使你的解决方法很糟糕,我也会遇到同样的错误
  • 你使用自己的时区而不是“欧洲/柏林”吗?
  • 对不起,我有一个逻辑错误....您还必须将偏移量添加到 UTC。请参阅我编辑的答案。我已经对其进行了测试,它对我有用。
【解决方案2】:

您可以使用 Carbon 生成时间戳并提供时区。试试吧:

Carbon::now()->format('c')

【讨论】:

  • 好建议,谢谢。但后来我收到一个错误,因为 2017-04-14T02:36:34+00:00 不是我的数据库所期望的格式,它是 UTC 而不是我的本地时间。
猜你喜欢
  • 2018-01-01
  • 2013-09-22
  • 1970-01-01
  • 2011-08-14
  • 2020-09-12
  • 2020-03-01
  • 2018-02-04
  • 1970-01-01
  • 2012-07-03
相关资源
最近更新 更多