Linux UTC系统下将指定时区日期转为UTC起止时间的PHP实现
没问题,我来帮你搞定这两个需求——先把Linux服务器改成UTC时区,再用PHP算出目标时区对应日期的UTC起止时间,方便你查询数据库~
一、将Linux服务器设置为UTC时区
不同Linux发行版的设置方式略有差异,我给你两种常用的方法:
方法一:用timedatectl(适用于systemd系统,比如Ubuntu 16.04+、CentOS 7+)
- 先查看当前服务器的时区状态:
timedatectl status - 设置为UTC时区:
sudo timedatectl set-timezone UTC - 再次执行
timedatectl status验证,看到Time zone: UTC (UTC, +0000)就说明设置成功了。
- 先查看当前服务器的时区状态:
方法二:传统符号链接方式(适用于非systemd系统)
- 先备份原来的时区配置文件:
sudo mv /etc/localtime /etc/localtime.bak - 创建UTC时区的符号链接:
sudo ln -sf /usr/share/zoneinfo/UTC /etc/localtime - 执行
date命令验证,输出里会显示UTC字样,比如Sat Mar 23 15:00:00 UTC 2024。
- 先备份原来的时区配置文件:
二、PHP中获取目标时区对应日期的UTC起止时间
你举的例子是America/Denver时区的2018-03-24,要获取该日期当日记录的UTC时间范围,核心思路是:先构造目标时区当日的开始和结束时刻,再把这两个时刻转换为UTC时区。
1. 已知目标日期的情况
比如明确要处理2018-03-24这个日期,代码可以这么写:
// 定义目标时区 $targetTz = new DateTimeZone('America/Denver'); // 构造目标日期的00:00:00时刻(目标时区) $dayStart = new DateTime('2018-03-24 00:00:00', $targetTz); // 转换为UTC时区 $dayStartUtc = clone $dayStart; $dayStartUtc->setTimezone(new DateTimeZone('UTC')); // 构造目标日期的23:59:59时刻(目标时区) $dayEnd = new DateTime('2018-03-24 23:59:59', $targetTz); // 转换为UTC时区 $dayEndUtc = clone $dayEnd; $dayEndUtc->setTimezone(new DateTimeZone('UTC')); // 输出结果 echo "目标时区当日开始的UTC时间:" . $dayStartUtc->format('Y-m-d H:i:s') . "\n"; echo "目标时区当日结束的UTC时间:" . $dayEndUtc->format('Y-m-d H:i:s') . "\n";
执行后,America/Denver时区的2018-03-24 00:00:00会转换为UTC的2018-03-24 06:00:00(因为当时是夏令时,Denver比UTC晚6小时),而23:59:59会转换为2018-03-25 05:59:59。
2. 基于当前时间自动获取目标时区日期的情况
如果要根据当前时间,自动获取目标时区当天的UTC范围,代码可以调整为:
$targetTz = new DateTimeZone('America/Denver'); // 获取当前时间在目标时区的日期 $nowInTarget = new DateTime('now', $targetTz); $currentDate = $nowInTarget->format('Y-m-d'); // 构造当日开始和结束时刻 $dayStart = new DateTime($currentDate . ' 00:00:00', $targetTz); $dayStartUtc = clone $dayStart; $dayStartUtc->setTimezone(new DateTimeZone('UTC')); $dayEnd = new DateTime($currentDate . ' 23:59:59', $targetTz); $dayEndUtc = clone $dayEnd; $dayEndUtc->setTimezone(new DateTimeZone('UTC')); echo "当前目标时区日期的UTC开始时间:" . $dayStartUtc->format('Y-m-d H:i:s') . "\n"; echo "当前目标时区日期的UTC结束时间:" . $dayEndUtc->format('Y-m-d H:i:s') . "\n";
小提示:更严谨的查询边界
用23:59:59作为结束时间可能会漏掉毫秒级的记录(比如刚好在2018-03-24 23:59:59.999创建的记录),更稳妥的方式是用次日的00:00:00作为结束边界,查询时用小于这个时间,而不是小于等于:
// 构造目标日期的次日00:00:00时刻(目标时区) $nextDayStart = new DateTime($currentDate . ' +1 day', $targetTz); $nextDayStartUtc = clone $nextDayStart; $nextDayStartUtc->setTimezone(new DateTimeZone('UTC')); // 数据库查询条件就写成: // created_at >= '$dayStartUtc' AND created_at < '$nextDayStartUtc'
这样就不会漏掉任何属于目标日期的记录啦。
内容的提问来源于stack exchange,提问作者Steve Lloyd




