PHP date()函数特定时间戳时间偏移问题及解决方案求助
问题根源:夏令时(DST)时区切换
这绝对是夏令时(Daylight Saving Time)切换搞的鬼!你的服务器时区应该设置为伊朗时区(Asia/Tehran),而伊朗每年3月21-22日左右(对应伊朗历新年)会切换夏令时:将时钟从标准时间(IRST,UTC+3:30)拨快1小时到夏令时(IRDT,UTC+4:30),直接跳过了当天00:00到00:59:59这个时间段——这就是你遇到“一小时丢失”的核心原因。
具体原因拆解
- 时间戳
1490128200对应的UTC时间是2017-03-21 21:30:00,如果按伊朗标准时间(IRST)计算,正好是2017-03-22 00:00:00。但此时伊朗已经完成夏令时切换,这个时间点在本地时区里是不存在的,PHP会自动将其映射到下一个有效的时间点:2017-03-22 01:00:00(IRDT)。 - 前一秒的
1490128199对应的UTC是2017-03-21 21:29:59,此时还没到夏令时切换时间,所以输出的是伊朗标准时间的2017-03-21 23:59:59 pm。
解决方案
1. 优先使用UTC进行时间存储与计算
时间戳本质是基于UTC的Unix时间,建议始终用UTC处理核心逻辑,展示时再转换为目标时区,从根源避免夏令时歧义:
$timestamp = 1490128200; // 1. 用UTC处理时间(存储/计算环节) $utcDateTime = gmdate('Y-m-d H:i:s', $timestamp); // 2. 展示时转换为伊朗时区 $dt = DateTime::createFromFormat('Y-m-d H:i:s', $utcDateTime, new DateTimeZone('UTC')); $dt->setTimezone(new DateTimeZone('Asia/Tehran')); echo $dt->format('Y-m-d H:i:s a');
2. 明确设置时区并使用DateTime类处理
避免依赖服务器默认时区配置,同时用DateTime类更精准地处理时区转换(它会自动处理夏令时规则):
// 脚本开头明确设置时区 date_default_timezone_set('Asia/Tehran'); $timestamp = 1490128200; $dt = new DateTime(); $dt->setTimestamp($timestamp); // 如果你需要强制展示为标准时间(不切换夏令时),可以改用固定偏移时区 // $dt->setTimezone(new DateTimeZone('Etc/GMT-3:30')); echo $dt->format('Y-m-d H:i:s a');
3. 业务场景允许的话,使用无夏令时的固定偏移时区
如果你的业务不需要遵循当地夏令时规则,可以用固定偏移的时区(比如Etc/GMT-3:30对应IRST的UTC+3:30),这样就不会出现时间跳变的问题,但注意这可能不符合当地的官方时间规范。
内容的提问来源于stack exchange,提问作者Mohammad Ghasemi
相关产品推荐
相关产品推荐

