我创建一个实体,datetime设置为08:50:35,时区为“+00:00”。我重新加载实体,日期时间为08:50:35,时区为“+02:00”。时区变了!
将symfony3.4与条令、php7.2、mysql 5.7和ubuntu16.4或debian 8结合使用。
我使用一个外部库,它使用datetime::createfromformat from timestamp指令。所以留着它就好了。
以下是我将问题简化为的代码:
// Create entity with date.
$report = new CronReport();
$date = \DateTime::createFromFormat('U', '1534755035');
var_dump($date); // object(DateTime)#536 (3) {
// ["date"]=> string(26) "2018-08-20 08:50:35.000000"
// ["timezone_type"]=> int(1)
// ["timezone"]=> string(6) "+00:00" }
$report->setRunAt($date);
$report->setRunTime(0);
$report->setExitCode(0);
$report->setOutput('');
$this->em->persist($report);
$this->em->flush();
// Reload Entity.
$id = $report->getId();
$this->em->detach($report);
$report = this->em->getRepository('CronCronBundle:CronReport')->find($id);
$date = $report->getRunAt();
var_dump($date); // object(DateTime)#550 (3) {
// ["date"]=> string(26) "2018-08-20 08:50:35.000000"
// ["timezone_type"]=> int(3)
// ["timezone"]=> string(12) "Europe/Paris" }
表创建声明:
CREATE TABLE `cron_report` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) DEFAULT NULL,
`run_at` datetime NOT NULL,
`run_time` double NOT NULL,
`exit_code` int(11) NOT NULL,
`output` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `IDX_B6C6A7F5BE04EA9` (`job_id`),
CONSTRAINT `FK_B6C6A7F5BE04EA9` FOREIGN KEY (`job_id`) REFERENCES `cron_job` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
怎么了?如何设置实体日期时间并保留其时区?
1条答案
按热度按时间dzjeubhm1#
问题似乎是您的php时区设置的值与
UTC
,即Europe/Paris
. 这是在您的phi.ini
或在运行时使用date_default_timezone_set("Europe/Paris")
或者ini_set("date.timezone", "Europe/Paris")
. 您可以通过运行php -i | grep timezone
(对于cli)或var_dump(ini_get("date.timezone"))
在运行时。使用条令结合mysql处理datetime对象是它自己的主题。简而言之,数据库不关心存储在数据库中的值的时区
datetime
柱。当您将datetime对象传递给条令时,它将在数据库中存储时间而不是时区。当再次检索值时,它将使用数据库中的值创建datetime对象,但要使用php的默认时区。有几种解决方案:
您可以考虑使用具有时区支持的列类型并使用
datetimetz
. 注意,这不适用于mysql作为底层数据库。如果应用程序中只有一个时区,请在php中将其设置为默认时区,并在持久化之前将所有datetime对象转换为该时区。
如果有多个时区,则必须将时区与
datetime
价值观。在这种情况下,应该将内部时区设置为utc,并在持久化之前将datetime对象转换为utc。然后,在从实体检索日期时间时,必须再次设置正确的时区。或者您可能会发现直接将时间存储为unix时间戳(定义为utc)并动态创建datetime示例更容易。取决于您的用例。阅读由条令团队撰写的关于datetime处理的文章,以获得关于利弊的扩展讨论,了解更多信息:https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/cookbook/working-with-datetime.html#handling-日期时间类型的不同时区