当date_default_timezone_set()被禁用时,首选在项目目录创建.user.ini文件写入date.timezone="asia/shanghai";若不可用,则每次使用datetime类显式传入datetimezone对象;环境变量tz已失效,不可用。

PHP date_default_timezone_set() 被禁用或无效怎么办
很多共享虚拟主机(如某些 cPanel 或老旧 PHP 环境)会通过 disable_functions 禁用 date_default_timezone_set(),或者在 php.ini 中锁定时区(date.timezone 设为只读),导致你在脚本里调用该函数直接报错或静默失败。
这不是代码写错了,而是服务器层面的权限限制。此时硬改函数没用,得绕过运行时设置,改用更底层、更早生效的方式。
- 优先检查
phpinfo()输出中date.timezone的值和 “Master Value” 是否可覆盖;若 “Local Value” 显示为no value且函数调用失败,说明被禁用 - 不要尝试用
ini_set('date.timezone', ...)—— 它和date_default_timezone_set()同样被多数主机屏蔽 - 如果能上传自定义
.user.ini(支持 PHP-FPM 的主机常见),这是最轻量有效的替代
用 .user.ini 设置时区(无需重启 PHP)
.user.ini 是 PHP 内置支持的 per-directory 配置文件,只要主机启用 user_ini.filename(默认就是 .user.ini),且未禁用该功能,它就能在脚本执行前生效,优先级高于 php.ini 的 Master Value。
在网站根目录或具体项目目录下新建文件:
立即学习“PHP免费学习笔记(深入)”;
date.timezone = "Asia/Shanghai"
注意:.user.ini 只支持部分配置项,date.timezone 是明确支持的;它不支持条件语句或 PHP 代码,纯静态 INI 格式。
- 保存后需等待最多 5 分钟(PHP 默认缓存时间),或手动清空 OPcache(若有权限)
- 若仍不生效,检查主机是否关闭了
user_ini.enable(可通过phpinfo()查看) - 路径必须正确:文件名必须是
.user.ini(开头带点),不能叫user.ini或timezone.ini
当 .user.ini 也不可用时:用 DateTimeZone 显式传参
如果连 .user.ini 都被禁(比如某些超严格 Windows 主机或 CGI 模式),那就放弃全局时区设定,改为在每次使用时间相关函数时,显式指定时区对象。
所有依赖时区的操作都必须绕开全局状态:
- 不用
date(),改用new DateTime('now', new DateTimeZone('Asia/Shanghai')) - 不用
strtotime()解析带时区的字符串,改用DateTime::createFromFormat()+ 显式时区 - 数据库时间字段入库前,统一转成 UTC 存储;展示时再用
DateTime转回本地时区,避免依赖服务器默认时区
示例:
$dt = new DateTime('2024-06-15 14:30:00', new DateTimeZone('Asia/Shanghai'));
echo $dt->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s'); // 输出 UTC 时间
为什么不能靠 $_SERVER['TZ'] 或环境变量
有人试过在 .htaccess 里加 SetEnv TZ Asia/Shanghai,或在 shell 启动前设环境变量 —— 这对 CLI 模式可能有效,但绝大多数虚拟主机用的是 Apache + mod_php 或 PHP-FPM,TZ 环境变量不会自动注入到 PHP 的时区逻辑中,date() 和 DateTime 完全无视它。
PHP 自 5.4 起就不再读取 TZ 环境变量作为默认时区来源,这个方式早已失效,不是兼容性问题,是设计移除。
真正可靠的路径只有三条:服务器级 php.ini(你通常没权限)、.user.ini(推荐首选)、或代码层显式传参(兜底方案)。别在环境变量上浪费调试时间。











