petrknap/zoned-datetime-persistence
Composer 安装命令:
composer require petrknap/zoned-datetime-persistence
包简介
Timezone aware date-time persistence
关键字:
README 文档
README
Many data storage systems (like MySQL) do not natively support storing timezone information alongside date-time values. This limitation introduces ambiguity when handling zoned date-times — particularly in applications operating across multiple timezones or even within a single timezone that observes multiple offsets (e.g. due to daylight saving time).
This package addresses the issue by providing tools that treat zoned date-time as a pair consisting of:
- the UTC date-time value, and
- a companion value that explicitly captures the corresponding timezone information.
Implemented
UTC with local date-time
UtcWithLocal
The most useful approach is to store the UTC date-time together with its local counterpart. This dual representation enables seamless manipulation of date-time values directly within storage system. The local date-time is ideal for grouping and filtering based on user or business context, while the UTC value ensures consistent and accurate sorting across timezones.
How to use it
There is built-in support for
the Jakarta Persistence API (see Note.java and JpaTest.java),
the Doctrine ORM (see Note.php and DoctrineTest.php),
the Eloquent (see NoteModel.php and EloquentTest.php),
and, of course, it can be integrated manually into any project, giving you full flexibility to adapt it to your specific needs.
namespace PetrKnap\Persistence\ZonedDateTime; $em = DoctrineTest::prepareEntityManager(); # persist entity $em->persist(new Some\Note( createdAt: new \DateTimeImmutable('2025-10-30 23:52'), content: "It's dark outside...", )); $em->flush(); # insert data manually (static call) $now = new \DateTimeImmutable('2025-10-26 02:45', new \DateTimeZone('CEST')); $em->getConnection()->insert('notes', [ 'created_at__utc' => ZonedDateTimePersistence::computeUtcDateTime($now)->format('Y-m-d H:i:s'), 'created_at__local' => $now->format('Y-m-d H:i:s'), 'content' => 'We still have summer time', ]); # insert data manually (object instance) $now = new UtcWithLocal(new \DateTimeImmutable('2025-10-26 02:15', new \DateTimeZone('CET'))); $em->getConnection()->insert('notes', [ 'created_at__utc' => $now->getUtcDateTime('Y-m-d H:i:s'), 'created_at__local' => $now->getLocalDateTime('Y-m-d H:i:s'), 'content' => 'Now we have winter time', ]); # select entities $notes = $em->createQueryBuilder() ->select('note') ->from(Some\Note::class, 'note') ->where('note.createdAt.local BETWEEN :from AND :to') ->orderBy('note.createdAt.utc') ->getQuery() ->execute(['from' => '2025-10-26 00:00', 'to' => '2025-10-26 23:59']); foreach($notes as $note) { echo $note->getCreatedAt()->format('Y-m-d H:i T') . ': '. $note->getContent() . PHP_EOL; }
2025-10-26 02:45 GMT+0200: We still have summer time
2025-10-26 02:15 GMT+0100: Now we have winter time
UTC with timezone
UtcWithTimezone
If you want to preserve the original timezone as is, you cannot use UtcWithLocal, because it works over fixed offsets.
In this case, you need to use this implementation.
namespace PetrKnap\Persistence\ZonedDateTime; $now = (new \DateTime('2025-03-30 01:45', new \DateTimeZone('Europe/Prague'))); echo 'UtcWithTimezone: ' . (new UtcWithTimezone($now)) ->toZonedDateTime() ->modify('+1 hour') ->format('Y-m-d H:i T' . PHP_EOL); echo 'UtcWithLocal: ' . (new UtcWithLocal($now)) ->toZonedDateTime() ->modify('+1 hour') ->format('Y-m-d H:i T' . PHP_EOL);
UtcWithTimezone: 2025-03-30 03:45 CEST
UtcWithLocal: 2025-03-30 02:45 GMT+0100
UTC with system timezone
UtcWithSystemTimezone
The most compact approach is to store only the UTC date-time.
This serves as an alternative to MySQL's TIMESTAMP, Postgres's TIMESTAMP WITH TIMEZONE, and custom ORM types.
It offers full range of DateTime, avoids normalization on connection, adds .utc into your queries for better readability and didn't need special configuration.
UTC date-time converter / type / cast
UtcDateTimeConverterJakarta Persistence API
This converter transparently manages conversions of ZonedDateTime, including JPQL parameters.
That means you no longer need to worry about manual timezone adjustments.
For examples, see the attributes Note.createdAtUtc and Note.deletedAtUtc and the JpaTest.
UtcDateTimeTypeDoctrine ORM
In contrast to UtcDateTimeConverter, this type does not automatically adjust the timezone of DQL parameters.
You must therefore provide the type when you are calling setParameter on your queries.
Also, you have to register the type in your Doctrine configuration manually.
For examples, see the attributes Note.createdAtUtc and Note.deletedAtUtc and the DoctrineTest.
AsUtcDateTimeEloquent
In contrast to UtcDateTimeConverter and UtcDateTimeType, this cast may or may not adjust the timezone of any input.
You should therefore handle timezone conversions explicitly everytime you are providing date-time into Eloquent.
But the conversion after hydration works well.
For examples, see the attributes NoteModel.created_at_utc and NoteModel.deleted_at_utc and the EloquentTest.
You can support this project via donation.
The project is licensed under the terms of the LGPL-3.0-or-later.
petrknap/zoned-datetime-persistence 适用场景与选型建议
petrknap/zoned-datetime-persistence 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.74k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 11 月 06 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「orm」 「persistence」 「sql」 「doctrine」 「helper」 「dql」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 petrknap/zoned-datetime-persistence 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 petrknap/zoned-datetime-persistence 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 petrknap/zoned-datetime-persistence 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
This bundle provides tools to build persistence-agnostic storage layer.
Propel2 is an open-source Object-Relational Mapping (ORM) for PHP 5.5 and up.
Kinikit - PHP Application development framework MVC component
PHP Database ORM for Symfony1. Do NOT use for new projects: please move to a newest Symfony release and Doctrine2
Query filtering in your frontend
Database/ORM-agnostic query construction helper
统计信息
- 总下载量: 1.74k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 42
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: LGPL-3.0-or-later
- 更新时间: 2025-11-06