根本原因是wheretime的between默认右边界为00:00:00而非23:59:59,导致datetime字段查询漏掉区间最后一天的非零点数据;正确做法是显式指定右边界为23:59:59或改用>=/

whereTime 用 between 查日期区间时,最后一天容易漏掉,根本原因不是循环逻辑错,而是时间边界没对齐。
whereTime 的 between 默认不包含右边界末秒
whereTime 对 datetime 字段做 between 查询时,传入的字符串如 '2026-08-05' 和 '2026-08-06',会被直接拼成:
WHERE create_time BETWEEN '2026-08-05 00:00:00' AND '2026-08-06 00:00:00'
注意:右边界是 00:00:00,不是 23:59:59。所以 2026-08-06 这整天的数据(比如 2026-08-06 14:22:33)根本不会被查到。
-
whereTime('create_time', 'between', ['2026-08-05', '2026-08-06'])→ 漏掉 8 月 6 日所有非零点数据 - 正确做法是显式补上右边界最大时间点
推荐写法(安全、明确、兼容所有字段类型):
-
whereTime('create_time', '>=', '2026-08-05') whereTime('create_time', '
或者一步到位用 between 但手动指定右边界:
whereTime('create_time', 'between', ['2026-08-05', '2026-08-06 23:59:59'])
如果字段是 date 类型(只存日期,无时间),那 between ['2026-08-05', '2026-08-06'] 是 OK 的,MySQL 会自动按日对齐;但只要字段是 datetime 或 timestamp,就必须考虑时间部分。
字段类型不一致时,whereTime 行为会悄悄失效
- 如果数据库字段是
int存时间戳,whereTime会尝试把字符串转成时间戳,但规则依赖strtotime(),遇到模糊格式(如'2026/08/06')可能解析失败或偏移 - 更稳妥的做法是:字段为时间戳时,直接用
where+strtotime()
例如:
-
where('create_time', '>=', strtotime('2026-08-05')) where('create_time', '
这样绕过 whereTime 的字符串隐式处理,也避免时区干扰(前提是 PHP 时区和数据库一致)。
用 Time::today() 等辅助方法时,注意它返回的是时间戳,不是字符串
Time::today() 返回的是两个整数时间戳:$start 和 $end(后者是当天 23:59:59 的时间戳),直接用于 where 即可:
-
where('create_time', 'between', [Time::today()[0], Time::today()[1]]) - 不要再套
whereTime,否则会二次转换出错
如果硬要用 whereTime,得先转成格式化字符串:
whereTime('create_time', 'between', [date('Y-m-d H:i:s', $start), date('Y-m-d H:i:s', $end)])
但多此一举,不如直接 where。
日期边界问题从来不是“少循环一天”,而是 SQL 条件本身没覆盖到那天的全部时间点。动手前先确认字段类型、时区配置、以及你真正想表达的语义——是「包含整个自然日」,还是「精确到秒」。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











