You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony定时任务时区异常:邮件发送时间偏差问题排查

系统信息
Ubuntu系统时区:Asia/Tokyo(JST)
MySQL(RDS)时区:跟随系统
定时任务命令
30 * * * * cd project && php bin/console command-name
核心代码实现

命令execute方法

在命令的execute()方法开头通过EntityManager调用查询构建器:

$em = $this->getContainer()->get('doctrine')->getManager();
$newsletters = $em->getRepository('AppBundle:Newsletter')->getNewsletterForDelivery()->getQuery()->getResult();

查询构建器初始代码

命令对应的查询构建器逻辑:

public function getNewsletterForDelivery()
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb->select('n')
        ->from('AppBundle:Newsletter', 'n')
        ->andWhere("DATE_FORMAT(n.sendDatetime,'%Y-%m-%d %H:%i') <= DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i')")
        ->andWhere('n.status = :status')
        ->andWhere('n.sendStatus = :sendStatus')
        ->setParameter('status', Newsletter::STATUS_DEFAULT)
        ->setParameter('sendStatus', Newsletter::SEND_STATUS_WAITING);

    return $qb;
}
初始问题现象

预期查询构建器能按条件获取待发送邮件,但通过cron执行时,邮件总是延迟9小时发送,问题出在时间比较条件:

->andWhere("DATE_FORMAT(n.sendDatetime,'%Y-%m-%d %H:%i') <= DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i')")

实际执行结果:

标题     计划发送时间     实际接收时间
Test 1  | 2024-11-06 16:56 | 2024-11-07 01:30
Test 2  | 2024-11-07 13:00 | 2024-11-07 22:30
test 3  | 2024-11-07 13:25 | 2024-11-07 22:30
Test 4  | 2024-11-13 09:15 | 2024-11-13 18:30 

可见即使MySQL和系统时区均为JST,实际接收时间仍比计划晚9小时。

尝试修复后的新问题

为补偿时区问题,尝试将now时间加9小时,调整后的查询构建器代码:

public function getNewsletterForDelivery()
{
    // 调整`now`加9小时,解决因系统/Symfony时区问题导致的邮件延迟发送
    $adjustedNow = new \DateTime(); // 当前时间
    $adjustedNow->modify('+9 hours'); // 增加9小时

    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb->select('n')
        ->from('AppBundle:Newsletter', 'n')
        // 比较sendDatetime与调整后的当前时间
        ->andWhere("DATE_FORMAT(n.sendDatetime, '%Y-%m-%d %H:%i') <= DATE_FORMAT(:adjustedNow, '%Y-%m-%d %H:%i')")
        ->andWhere('n.status = :status')
        ->andWhere('n.sendStatus = :sendStatus')
        ->setParameter('adjustedNow', $adjustedNow) // 设置调整后的当前时间
        ->setParameter('status', Newsletter::STATUS_DEFAULT)
        ->setParameter('sendStatus', Newsletter::SEND_STATUS_WAITING);

    return $qb;
}

调整后的执行结果出现新问题:邮件被提前发送,即使计划发送时间未到:

标题     计划发送时间     实际接收时间
Test 1  | 2024-11-21 17:00 | 2024-11-21 17:30  正常
Test 2  | 2024-11-21 17:15 | 2024-11-21 17:30  正常
Test 3  | 2024-11-21 17:30 | 2024-11-21 17:30  正常
Test 4  | 2024-11-21 17:45 | 2024-11-21 17:30  异常
Test 5  | 2024-11-21 18:00 | 2024-11-21 17:30  异常
Test 6  | 2024-11-21 18:15 | 2024-11-21 17:30  异常
Test 7  | 2024-11-21 18:30 | 2024-11-21 17:30  异常
Test 8  | 2024-11-21 18:45 | 2024-11-21 17:30  异常
Test 9  | 2024-11-21 19:00 | 2024-11-21 17:30  异常
关键注意点
  • 移除条件中的DATE_FORMAT,直接比较原始datetime字段,结果与之前一致
  • 手动从CLI执行命令时能获取符合条件的邮件数据:
当前时间: 2024-11-22 17:08:18 (执行时的当前时间)
Test 1: 2024-11-21 17:00:00 (数据库中的实际时间)
问题总结

手动执行命令时,能正确获取符合计划发送时间的邮件;但通过cron执行时,会提前获取计划发送时间晚于当前时间2小时的邮件。


内容的提问来源于stack exchange,提问作者Mr. Kenneth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:24:54