使用PDO操作ACCESS .MDB时,插入的DateTime字段偏移2小时的问题
解决PDO连接Access MDB时DateTime字段时区偏移问题
我之前在Windows环境下用PDO连接Access数据库时也碰到过一模一样的时区偏移问题,结合你处于意大利时区(夏令时为UTC+2)的情况,这个问题的核心原因很明确:Windows的Microsoft Access ODBC驱动在处理DateTime类型时,会自动将本地时间转换为UTC存储,查询时却直接返回UTC时间,没有转回你的本地时区,这就导致了查询结果比实际插入时间提前2小时。
下面给你两个可靠的解决思路:
方案一:插入时传递格式化的本地时间字符串
避免直接传入DateTime对象,而是手动格式化符合Access要求的时间字符串,绕过驱动的自动时区转换:
<?php // 明确指定意大利时区创建时间对象 $dateHour = new DateTime('now', new DateTimeZone('Europe/Rome')); // 格式化为Access可识别的字符串格式 $formattedDate = $dateHour->format('Y-m-d H:i:s'); $sql = "INSERT INTO table (DateTime, ... ) VALUES ( ?, ... )"; $s = $db->prepare($sql); // 传入格式化后的字符串而非DateTime对象 $s->execute(array($formattedDate)); ?>
这样插入的时间会直接以你本地时区的时间写入Access,查询时返回的结果就和系统时间一致了。
方案二:查询时将UTC时间转回本地时区
如果已经有历史数据需要处理,或者不想修改插入逻辑,可以在查询后手动将返回的UTC时间转换为意大利时区:
<?php $sql = "SELECT * FROM table WHERE ID = ?"; // 执行查询并获取结果... // 将返回的UTC时间转换为意大利时区 $utcDateTime = new DateTime($result['DateTime'], new DateTimeZone('UTC')); $utcDateTime->setTimezone(new DateTimeZone('Europe/Rome')); // 输出正确的本地时间 var_dump($utcDateTime->format('Y-m-d H:i:s')); // 2018-05-22 12:29:02 ?>
补充说明
Access的DateTime类型本身并不存储时区信息,它本质是一个双精度浮点数,代表从1899-12-30开始的天数和时间占比。问题的根源完全在于ODBC驱动的默认行为——它会自动做UTC转换,而这个行为在非MySQL的场景下很容易被忽略。
内容的提问来源于stack exchange,提问作者Giuseppe Lodi Rizzini
相关产品推荐
相关产品推荐

