对于符合 ISO8601 的日期时间
2004-10-19 10:23:54+02
是否可以将该值(具有
+02
偏移量)反映在存储的列值中,并在选择时也保留下来?
根据我对文档的适当部分的阅读Postgres的默认行为是转换为UTC,此时原始偏移量会丢失。这当然是我所看到的。
数据是通过 ORM 访问的,该 ORM 无法添加任何特殊的 tz 转换,因此我确实需要简单地存储具有原始偏移量的日期时间,并在选择时反映该值。
对于任何渴望告诉我这是同一时间实例的人来说,保存该值对于该数据具有重要意义。
正如您自己已经弄清楚的那样,时区根本不会使用Postgres日期/时间类型保存,甚至不会使用
timestamptz
保存。它的作用分别只是输入修饰符或输出修饰符。仅保存值(时间点)。此相关答案中的详细信息:
因此,如果你想保留输入字符串的那部分,你必须从字符串中提取出来并自己保存。我会使用这样的表格:
CREATE TABLE tstz
...
, ts timestamp -- without time zone
, tz text
)
tz
,即 text
,可以保存数字 offset 以及时区 缩写,或时区 name。
困难在于根据解析器遵循的所有各种规则并且以不易破坏的方式提取时区部分。不要编写自己的程序,而是让解析器完成工作。考虑这个演示:
WITH ts_literals (tstz) AS (
VALUES ('2013-11-28 23:09:11.761166+03'::text)
, ('2013-11-28 23:09:11.761166 CET')
, ('2013-11-28 23:09:11.761166 America/New_York')
)
SELECT tstz
, tstz::timestamp AS ts
, right(tstz, -1 * length(tstz::timestamp::text)) AS tz
FROM ts_literals;
日期和时间之间有或没有
T
均可使用。关键逻辑在这里:
right(tstz, -1 * length(tstz::timestamp::text)) AS tz
在修剪解析器识别为日期/时间组件的长度后,获取时间戳字符串的剩余部分。正如您所说,这取决于输入:
经过验证的 ISO 8601 字符串
Java 开发人员可以将 Joda Time 与 Jadira UserType 的
PersistentDateTimeAndZone
结合使用。示例:
@Basic(optional = false)
@Columns(columns = { @Column(name = "modificationtime"),
@Column(name = "modificationtime_zone") })
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTimeAndZone")
@Index(name = "payment_modificationtime_idx")
private DateTime modificationTime = null;
在此示例中,
DateTime
信息分为 2 列:
modificationtime timestamp without time zone
以 UTC 时区存储时间戳modificationtime_zone varchar(255)
将时区 ID 存储为字符串(例如 America/Caracas
)虽然 Joda Time 和 Jadira(以及 Hibernate)特定于 Java(并且是“事实上的”方法),但上述构建 RDBMS 列以存储时间戳和时区的方法可以应用于任何编程语言。