php原则:创建实体后不保留日期时区

vnzz0bqm  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(356)

我创建一个实体,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;

怎么了?如何设置实体日期时间并保留其时区?

dzjeubhm

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-日期时间类型的不同时区

相关问题