DateTime对象上的不同时区类型

37

我在Postgres上使用Doctrine2。在一个表中,我有两种不同类型的日期: birthdate:datecreated_at:datetimetz。它们都成为DateTime对象,但具有不同的timezone_type

以下是列表:

created_at datetimetz:

DateTime Object
(
    [date] => 2013-04-18 11:54:34
    [timezone_type] => 1
    [timezone] => +02:00
)

birthdate date:

生日日期
DateTime Object
(
    [date] => 1970-01-01 00:00:00
    [timezone_type] => 3
    [timezone] => Europe/Berlin
)

我需要以相同的方式格式化我的对象。两者都应该具有 timezone_type=3

我该如何做到这一点?


1
date_timezone_set ( DateTime $object , DateTimeZone $timezone ) - DevZer0
您提出的代码仅设置时区。在上面的列表中,时区相同,但呈现方式不同。 - lilly
如果在每个上使用$mytime->setTimezone(new DateTimezone('Europe/Berlin'))(或其他任何时区),则结果将是它们以相同的方式呈现。 - Jerry
2个回答

91

DateTime对象中的时间区域可以是以下三种类型之一:

  • 类型1:UTC偏移量,例如 new DateTime("2013年7月17日 -0300");
  • 类型2:时区缩写,例如 new DateTime("2013年7月17日 GMT");
  • 类型3:时区标识符,例如 new DateTime( "2013年7月17日", new DateTimeZone("Europe/London"));

只有附加了类型3时间区域的DateTime对象才能正确使用DST。

为了始终拥有类型3,您需要将时区作为此列表中接受的标识符存储在数据库中,并在实例化DateTime对象时将其应用。


1
嗯...我在数据库中存储了这种类型3的时区。问题似乎是Doctrine2返回了这些不同的时区类型(即使我明确传递了时区为\ DateTimeZone(“Europe / London”))。我认为我没有轻松访问修改Doctrine2行为的方法,因此我已经决定使用简单的时间戳与使用者类一起进行日期时间格式化。或者我可能忽略了什么?您是否曾经处理过来自Doctrine2 + Postgres的DateTime对象并使其正常工作? - lilly
3
我发现使用不同的ORM出现相同的问题,尽管很丑,但 $new=new DateTime(); $new->setTimestamp($old->getTimestamp()); 可以解决问题。将其包含在setter中可以减轻痛苦。 - Eugen Rieck
1
@Softlion 如果我在类型1的DateTime中添加6个月,它将会有1小时的偏差,因为它不知道大约在10月份发生的DST转换。而类型3将正确地考虑到这个转换。 - vascowhite
1
@vascowhite 这个映射在文档中有列出吗? - GPHemsley
1
@GPHemsley 我不这么认为。我是通过测试和阅读源代码找出来的。我依稀记得在某个地方看到过确认我的发现的评论,但那是很久以前的事了,我现在也回想不起来在哪里看到的了。 - vascowhite
显示剩余2条评论

1
我知道这是一个古老的帖子,但由于提到了Doctrine,我觉得有必要分享一下我最近在这个问题上的经验。
@vascowhite是正确的,但关于Doctrine(至少在我的配置中),通过HTTP发送到服务器(例如保存)的日期会被转换为时区类型2。Doctrine正确地处理它们并正确保存日期,但它不会转换时区类型。
如果您执行“保存并返回新值”类型的操作,请注意Doctrine将使用缓存的值(具有时区类型2)。当您期望时区类型3(通常在页面重新加载期间获得)时,这变得很重要。我们有一个自定义的日期转换器JS类,它期望时区类型3,但无法转换它。诚然,日期转换器应该考虑到这一点,但也应该意识到时区类型将是Doctrine中加载的最后一个值。保存后清除Doctrine的缓存将强制数据重新加载,并使用时区类型3。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接