PHP和DST转换问题

时间:2016-11-10 17:13:40

标签: php timezone dst

我无法理解我的代码如何适应DST,因为最近的更新不正确。我将基于UTC的日期时间存储在数据库中,然后将其转换回本地时区进行显示。如果PHP正在考虑DST,那么其他错误是因为我所有存储的日期都是1小时。

$stored_date = '2016-11-16 12:04:01'; // in UTC

$dateTime = new DateTime($stored_date, new DateTimeZone('UTC'));
$dateTimeZone = new DateTimeZone('America/New_York');
$dateTime->setTimezone($dateTimeZone);

print_r($dateTime);

上周,在夏令时结束之前,这将打印出2016-11-16 08:04:01。本周,现在DST已经结束,它打印出2016-11-16 07:04:01。如果PHP正确处理DST转换,为什么小时差异?

服务器设置(我不认为)并不重要,因为我在PHP中明确地进行转换,对吧?

我已经准备好开始用PHP检查DST是否生效并将转换偏移1小时,因为我无法弄清楚为什么在DateTime类中没有自动补偿该小时。

1 个答案:

答案 0 :(得分:0)

纽约市在这些时区之间切换:

  • 冬季:EST(东部标准时间)= UTC -5
  • 夏天:EDT(东部夏令时)= UTC -4

根据timeanddate.com,转换将于11月6日进行。因此结果是正确的:#!/usr/bin/env python3 import beatbox import sqlalchemy engine_str = 'mysql+mysqlconnector://db-username:db-pass@localhost/db-name' engine = sqlalchemy.create_engine(engine_str, echo=False, encoding='utf-8') connection = engine.connect() sf = beatbox._tPartnerNS service = beatbox.Client() service.serverUrl = 'https://test.salesforce.com/services/Soap/u/38.0' #I hard quoted it since I was to test against sandbox only. def export(objectSOQL): service.login('sfdc-username', 'sfdc-pass') query_result = service.query(objectSOQL) while True: for row in query_result[sf.records:]: SQL_query = 'INSERT INTO user(' \ 'id, ' \ 'name, ' \ 'department ' \ 'VALUES(' \ '\"{}\",\"{}\",\"{}\")'\ .format( row[2], row[3], row[4] ) try: connection.execute(SQL_query) except Exception as e: print(e) # This is key part which actually pulls records beyond 500 until sf.done becomes true which means the query has been completed. if str(query_result[sf.done]) == 'true': break query_result = service.queryMore(str(query_result[sf.queryLocator])) SOQL = 'SELECT id, Name, Department FROM User' export(SOQL)

换句话说,PHP完全了解DST,我们可以在以下代码中看到:

12 - 5 = 7
$dateTime = new DateTime('2016-11-05 12:04:01', new DateTimeZone('UTC'));
$dateTime->setTimezone(new DateTimeZone('America/New_York'));
echo $dateTime->format('r') . PHP_EOL;

$dateTime = new DateTime('2016-11-06 12:04:01', new DateTimeZone('UTC'));
$dateTime->setTimezone(new DateTimeZone('America/New_York'));
echo $dateTime->format('r') . PHP_EOL;

您可以检查系统时间数据库中的确切信息:

Sat, 05 Nov 2016 08:04:01 -0400
Sun, 06 Nov 2016 07:04:01 -0500
$timeZone = new DateTimeZone('America/New_York');
print_r($timeZone->getTransitions(mktime(0, 0, 0, 1, 1, 2016), mktime(0, 0, 0, 12, 31, 2016)));