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

如何在指定时间后查询当日未重置的用户目标以重置进度?

实现基于用户自定义重置时间的Goal自动重置逻辑

我之前做过类似的定时重置任务,结合你的需求,整理了完整的实现代码和逻辑说明:

首先,假设你的goals表除了progress和reset_time,还应该有一个last_reset_at字段(用来记录最后一次重置的时间,判断当日是否已重置)——如果还没有的话,建议先加上这个字段,它能帮我们准确判断哪些Goal需要重置。

下面是完整的Laravel代码示例(适配你给出的代码片段):

// 先获取UTC时间(因为你的重置时间是UTC时区的)
$now = \Carbon\Carbon::now('UTC');
$today = \Carbon\Carbon::today('UTC');

// 查询需要重置的Goal数据
$goals = \App\Goal::query()
    // 筛选「当日未重置」的Goal:要么从未重置过,要么最后重置时间早于今天
    ->where(function ($query) use ($today) {
        $query->whereNull('last_reset_at')
              ->orWhereDate('last_reset_at', '<', $today);
    })
    // 筛选「当前时间已过用户设置的重置时间」的Goal(只比较时间部分)
    ->whereTime('reset_time', '<=', $now->toTimeString())
    ->get();

// 执行重置操作
foreach ($goals as $goal) {
    $goal->update([
        'progress' => 0, // 把进度清零,根据你的需求调整
        'last_reset_at' => $now // 标记为已重置
    ]);
}

关键逻辑解释:

  • 时区统一:全程用UTC时间处理,避免服务器时区和用户设置的UTC重置时间出现偏差。
  • 当日未重置判断:用嵌套的where子句覆盖两种情况:新创建的Goal还没重置过(last_reset_at为null),或者上次重置是在昨天及更早的日期。
  • 重置时间判断:whereTime只比较时间部分(比如用户设的是04:00:00,现在UTC时间是04:01:00,就满足条件),不管日期,这样每天到点都会触发。

额外注意事项:

  • 如果你的reset_time字段存的是完整的datetime而非单独的时间字符串,那需要用数据库函数提取时间部分来比较,比如MySQL可以这么写:
    ->whereRaw('TIME(reset_time) <= ?', [$now->toTimeString()])
    
  • 调度任务要指定UTC时区,比如在Laravel的App\Console\Kernel.php中:
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('goals:reset')->everyMinute()->timezone('UTC');
    }
    
  • 给last_reset_at和reset_time加数据库索引,能提升每分钟查询的效率,避免数据量大时变慢。

内容的提问来源于stack exchange,提问作者Ross

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:31:03