mktime参数顺序为「时分秒月日年」,默认值取当前对应时间;$month范围1–12,省略须从左连续;时区依赖date_default_timezone_set,非参数控制;推荐用datetime替代。

mktime 的参数顺序和默认值怎么记才不乱
mktime 是 PHP 里少有的按「年月日时分秒」顺序传参的函数,不是 ISO 顺序,也不是时间戳转数组后的顺序。容易把 month 和 day 写反,尤其当后面几个参数省略时,默认值会悄悄影响结果。
它的完整签名是:mktime($hour, $minute, $second, $month, $day, $year) —— 注意:没有 $timezone 参数,它只用当前时区(date_default_timezone_set 控制)。
- 所有参数都可省略,但必须从左到右连续省略;不能只写
$year而不写前面的 - 省略
$hour时,默认为当前小时(不是 0),其他同理;这在定时任务里容易引发意外 -
$month是 1–12,不是 0–11;填 0 会被当成“上一年的 12 月”,填 13 会进位,这种自动归整常被误认为 bug - 如果传了
$year但没传$month或$day,PHP 会用当前月份/日期补全,而不是用 1 月 1 日
用 mktime 构造今天凌晨的时间戳为什么总差 8 小时
这不是 mktime 的错,是时区没设对。mktime 不接受时区参数,完全依赖运行时的默认时区。很多服务器默认是 UTC,而你本地开发环境可能是 Asia/Shanghai,导致生成的时间戳对应的是 UTC 时间,再用 date() 格式化就偏了。
- 上线前务必检查
date_default_timezone_get()返回值,别信 php.ini 里的注释 - 不要靠
ini_set('date.timezone', '...')临时改,它可能被后续代码覆盖;应该在入口文件最开头调用date_default_timezone_set('Asia/Shanghai') - 构造“今天 00:00:00”更稳的方式是:
mktime(0, 0, 0, (int)date('m'), (int)date('d'), (int)date('Y')),避免依赖当前时分秒
mktime 和 strtotime 哪个更适合解析固定格式的日期字符串
都不适合。mktime 是拼装时间戳的,不是解析器;strtotime 才是干这个的。但 strtotime 在遇到模糊输入(比如 "2023-02-30")时会静默修正成 3 月 2 日,而 mktime 对非法日期直接返回 false(PHP 7.0+)或负数(旧版),行为更可控。
立即学习“PHP免费学习笔记(深入)”;
- 如果你手头是拆好的年月日变量,用
mktime更轻量、无字符串解析开销 - 如果原始数据是字符串(如
"2023/05/20"),优先用strtotime,但记得用=== false判断失败,因为 1970-01-01 也会返回 0 - PHP 5.3+ 推荐用
DateTime::createFromFormat(),能严格校验格式,比如DateTime::createFromFormat('Y-m-d', '2023-02-30')会返回false,且允许自定义错误处理
PHP 8.1 之后 mktime 还安全吗?有没有替代方案
mktime 没被废弃,但官方文档已标记为“不推荐用于新项目”。它的问题不在功能,而在语义模糊:参数多、顺序反直觉、时区不可控、错误返回值不统一。
- 现代替代首选
new DateTime()或DateTimeImmutable,例如:(new DateTime())->setTime(0, 0, 0)->getTimestamp() - 需要纯函数式、无对象开销时,可用
gmmktime()显式指定 UTC,再手动加时区偏移(需谨慎) - 注意:
gmmktime参数顺序和mktime一致,但它返回的是 UTC 时间戳,不受date_default_timezone_set影响 - 所有涉及跨天、跨月计算的场景,别硬算参数,交给
DateTime::modify(),比如 “下个月第一天” 直接写->modify('first day of next month')
真正麻烦的从来不是参数怎么填,而是你得确认当前脚本跑在哪个时区、用户输入是否已被自动修正、以及那个看似正确的 false 返回值,到底是日期非法,还是刚好是 Unix 元年。











