最直接稳妥的方式是用 date() 函数配合正确时区设置,如 date('y-m') 获取“2024-03”,date('ym') 获取“202403”,(int)date('n') 获取无前导零月份数字;datetime 更适合需计算或校验的场景,而 getdate() 等旧函数已不推荐。

用 date() 获取年份和月份最直接
PHP8 里最常用也最稳妥的方式就是 date() 函数,它底层调用系统时区设置,不需要额外引入类或处理对象。只要确保 date_default_timezone_set() 已正确配置(比如 date_default_timezone_set('Asia/Shanghai')),结果就可靠。
常见写法:
// 获取 2024-03 这种格式(年-月,补零)
$date_str = date('Y-m');
// 获取 202403(无分隔符,常用于文件名或数据库分区)
$date_str = date('Ym');
// 只要月份数字(如 3,不是 03)
$month_num = (int) date('n');
注意:'m' 返回带前导零的月份(01–12),'n' 返回不带零的整数(1–12),别混淆。
DateTime 对象更适合需要计算或校验的场景
如果你不只是“取当前值”,还要做加减月份、判断是否跨年、或者跟其他时间比较,DateTime 更健壮。PHP8 对 DateTime 的类型推断和错误提示也更友好。
示例:
$now = new DateTime();
$year = $now->format('Y'); // 2024
$month = $now->format('m'); // '03'
$month_int = (int) $now->format('n'); // 3
// 下个月(自动处理 12→1 跨年)
$next_month = clone $now;
$next_month->modify('+1 month');
echo $next_month->format('Y-m'); // 2024-04
容易踩的坑:new DateTime() 默认用系统时区,但若服务器没设好,可能返回 UTC 时间;建议显式传入时区:new DateTime('now', new DateTimeZone('Asia/Shanghai'))。
别用 getdate() 或 localtime()
这两个函数返回数组,虽然也能拿到年月,但属于被长期弱化的旧接口,在 PHP8 中虽未移除,但返回结构松散、键名易记错(比如 getdate()['mon'] 是月份数字,['year'] 是四位年份),且无法直接支持时区切换。
更关键的是:它们不支持对象式链式操作,也不兼容 DateTimeInterface 类型约束——在强类型函数签名或依赖注入场景下会出问题。
-
getdate()返回的是关联数组,不是对象,不能调用方法 - 没有时区参数,硬编码依赖
date_default_timezone_set() - PHP8.2+ 已标记为“可能在未来版本弃用”
时区配置错误会导致年月偏差一整天
这是线上最常被忽略的问题:服务器时区是 UTC,但业务逻辑按北京时间走,结果凌晨 00:30 拿到的 date('Y-m') 还是上个月(比如北京时间 3 月 1 日 00:30 → UTC 是 2 月 29 日 16:30)。
检查方式:
echo date_default_timezone_get(); // 看输出是不是预期时区
echo date('Y-m-d H:i:s'); // 对照本地真实时间
修复建议:
- 在入口文件(如
index.php)顶部统一设时区,别依赖 php.ini - 避免在不同位置多次调用
date_default_timezone_set(),PHP8 不允许重复设置同个时区报Warning - 容器部署时,确认基础镜像的
TZ环境变量和 PHP 内部时区一致
真正麻烦的不是怎么取年月,而是取出来的值在分布式或跨时区服务里是否语义一致——这点往往到对账或归档时才暴露。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











