dsgnze6572 2013-01-04 22:43
浏览 72

Symfony 1.4 / Doctrine:将日期时间存储为UTC,但在生成的admin中将所有时间显示为Eastern Time

We have a Symfony project with a generated admin app, and we need datetime fields to show up as Eastern Time. Right now, Symfony is set to handle all datetime values as UTC. This is by design, since various other things that hook into this project deal with UTC datetimes. We just need the admin to display and accept datetime input as if the user was in the Eastern timezone.

Here's a short list of things we've done to try and accomplish this:

  1. Change the default_timezone setting in the app's setting.yml to 'America/New York'. First, it doesn't seem to actually change the way datetime fields display in the admin; it only seems to set date_default_timezone_set(). Second, we actually NEED PHP to treat times in UTC, since some of our helper functions are written to assume UTC. Finally, we need datetimes to be stored in the MySQL database as UTC, and because we've defined them all as DATETIME columns (not as timestamps) they are, as I understand it, timezone-naive. (I could be wrong here, though.)

  2. Modify the relevant admin form objects to translate datetimes from ET to UTC when saving/editing an object, and creating custom widgets to do the opposite translation when prefilling those same values in the edit form. So this actually worked for us, but there are significant issues here. We have to create custom widgets, for one; this wasn't that big of a deal, though. We also have to modify the admin form for every class that contains datetime fields. This is a bit more of a pain in the ass. We ALSO have to add helper functions to the affected classes, because while the admin forms will display the right values, if any of those datetime columns show up in the admin LIST, they will still appear as UTC times instead of ET times. And then we have to extend the Timestampable behavior as well, because THOSE also need to display in ET/store in UTC. This is a whole lot of work just to get the admin to display times in ET, which is not only fragile, but also needs to be added onto if we ever introduce new classes with datetime fields (or add datetime fields to current classes).

  3. Override the save() and load() functions on the affected classes. We tried translating the ET datetime strings we got from the admin form into UTC and changing the object using the built-in setter functions, and then calling the parent save(). That worked fine. Trying to do the same to the load() function in reverse, however, failed miserably. Calling the parent load() function was fine, but using the built-in setters to change the times back from UTC to ET failed. It turned out that the load() function wasn't actually executing at all, as far as we could tell; var_dump() and exit() commands wouldn't execute when we tried to load the form for an existing object. We still don't know why this doesn't work.

  4. Override the preSave() and postLoad() functions on the affected classes. We ran into the same problem as #4: preSave() worked fine but postLoad() failed.

  5. Override the preSave() function on the affected classes, and then override the relevant getter functions for the datetime fields in the class. This works, but ONLY if we get the original datetime values by accessing the object's internal $_data array as opposed to using the getters. We need to do this because apparently calling any setter will also eventually call the field's getter as well, resulting in us applying too many timezone translations. So this works, but accessing the $_data array feels like a giant hack that's begging to be broken.

Past that, we only have theoretical approaches that we haven't looked into yet. We could, for example, modify the definition of the datetime field itself in Symfony somewhere, either in Doctrine or somewhere else, but we couldn't think of a place to do this that wouldn't involve digging deep into the Doctrine core.

At this point, we're sort of stuck. All this seems like a hell of a lot of work just to get the admin to display datetimes as ET and save ET datetimes as UTC in the database, so we must be doing something wrong--we just can't figure out what we SHOULD be doing.

  • 写回答

2条回答 默认 最新

  • douhuo0884 2013-04-28 00:16
    关注

    We've done (2) basically - the database and system timezone is UTC as is right and natural, and we've got custom timezone-aware datetime widgets & validators.

    The other thing we've done is add a $model->getDateTimeObject($fieldName) method to our doctrine model base class (see http://oldforum.symfony-project.org/index.php/m/96066/), which will return a DateTime with the relevant DateTimeZone set.

    Eg:

    abstract class ourDoctrineRecord extends sfDoctrineRecord
    {
      /**
       * @param string $fieldName
       * @return DateTime
       */
      public function getDateTimeObject($fieldName)
      {
        // chose a relevant timezone based on user/app etc, or throw
      }
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)