PHP中DateTimeZone的getOffset方法为何不受传入DateTime影响?
为什么PHP的DateTimeZone::getOffset()方法传入不同DateTime对象返回结果一致?
我在理解PHP中DateTimeZone对象的getOffset方法时遇到了困惑——不管传入哪个DateTime对象,返回的偏移量结果始终一致。以下是我的测试代码:
public function testGetOffset() { // UTC offset is 00:00 (0 seconds) $timeZoneUtc = new \DateTimeZone('UTC'); $dateUTC = new \DateTime('now', $timeZoneUtc); // America/Sao_Paulo offset is -02:00 (-7200 seconds) $timeZoneSP = new \DateTimeZone('America/Sao_Paulo'); $dateSP = new \DateTime('now', $timeZoneSP); // America/New_York offset is -05:00 (-18000 seconds) $timeZoneNY = new \DateTimeZone('America/New_York'); $dateNY = new \DateTime('now', $timeZoneNY); $this->assertEquals(0, $timeZoneUtc->getOffset($dateUTC)); // true $this->assertEquals(0, $timeZoneUtc->getOffset($dateNY)); // true $this->assertEquals(0, $timeZoneUtc->getOffset($dateSP)); // true $this->assertEquals(-7200, $timeZoneSP->getOffset($dateUTC)); // true $this->assertEquals(-7200, $timeZoneSP->getOffset($dateNY)); // true $this->assertEquals(-7200, $timeZoneSP->getOffset($dateSP)); // true $this->assertEquals(-18000, $timeZoneNY->getOffset($dateUTC)); // true $this->assertEquals(-18000, $timeZoneNY->getOffset($dateNY)); // true $this->assertEquals(-18000, $timeZoneNY->getOffset($dateSP)); // true }
有没有人能帮我理解这一现象?
这其实是对DateTimeZone::getOffset()方法的核心作用理解有偏差,我来给你拆解清楚:
1. getOffset()的真正用途
这个方法的参数DateTime对象,不是用来指定“以哪个时区为基准计算偏移”,而是用来指定:要计算当前DateTimeZone实例代表的时区,在哪个具体时间点的UTC偏移量。
2. 底层逻辑
当你传入一个DateTime对象时,PHP会先把这个对象的时间转换为UTC时间,然后计算当前DateTimeZone对应的时区,在这个UTC时间对应的本地时刻,相对于UTC的偏移量。
3. 你的测试结果一致的原因
你所有的DateTime都是用'now'创建的——不管这些DateTime属于哪个时区,它们对应的UTC时间是完全相同的(都是同一时刻)。而每个时区在同一个UTC时刻的偏移量是固定的(比如当前圣保罗的偏移就是-7200秒,纽约是-18000秒),所以不管传入哪个'now'的DateTime,结果自然一致。
4. 验证:用不同时间点测试
如果换一个有夏令时变化的时间点,你就能看到结果差异了。比如纽约在每年3月会切换夏令时,切换前后的UTC偏移量会变化:
$timeZoneNY = new \DateTimeZone('America/New_York'); // 夏令时切换前的UTC时间:2024-03-10 01:00:00 $dtBeforeDST = new \DateTime('2024-03-10 01:00:00', new \DateTimeZone('UTC')); echo $timeZoneNY->getOffset($dtBeforeDST); // 输出 -18000(-5小时) // 夏令时切换后的UTC时间:2024-03-10 03:00:00 $dtAfterDST = new \DateTime('2024-03-10 03:00:00', new \DateTimeZone('UTC')); echo $timeZoneNY->getOffset($dtAfterDST); // 输出 -14400(-4小时)
总结
关键点是:getOffset()的参数是用来指定时间点,而非基准时区。同一个时区在不同时间点的偏移量可能因夏令时、时区规则变更等原因变化,但同一时间点的偏移量是固定的——这就是你测试结果一致的核心原因。
内容的提问来源于stack exchange,提问作者Juliana Amorim
相关产品推荐
相关产品推荐

